<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta http-equiv="pragma" content="no-cache" />
    <meta http-equiv="Cache-Control" content="no-cache, must-revalidate" />
    <meta http-equiv="expires" content="0" />
    <title>花卷猫框架</title>
</head>
<body>
    <canvas id="exampleCanvas" width="400" height="700" style="position: fixed; left: 0px; top: 0px;" />
    <script type="text/javascript">
    /*
    * 坐标结构
    */
    class FCPoint {
        // 构造函数
        constructor(ix, iy) {
            this.x = ix;
            this.y = iy;
        }
    };
    /*
    * 大小结构
    */
    class FCSize {
        // 构造函数
        constructor(icx, icy) {
            this.cx = icx;
            this.cy = icy;
        }
    };
    /*
    * 矩形结构
    */
    class FCRect {
        // 构造函数
        constructor(ileft, itop, iright, ibottom) {
            this.left = ileft;
            this.top = itop;
            this.right = iright;
            this.bottom = ibottom;
        }
    };
    /*
    * 转换颜色
    */
    function convertColor(inColor) {
        if (inColor.indexOf("rgba(") != -1) {
            let inStrs = inColor.replace("rgba(", "").replace(")", "");
            let strs = inStrs.split(',');
            if (strs.length >= 4) {
                let a = parseFloat(strs[3]);
                a /= 255;
                return "rgba(" + strs[0] + "," + strs[1] + "," + strs[2] + "," + a + ")";
            }
        }
        return inColor;
    }

    /*
    * 绘图结构
    */
    class FCPaint {
        constructor() {
            this.cancelClick = false; //是否退出点击
            this.canvas = null; //视图
            this.container = null; //容器
            this.context = null; //绘图上下文
            this.defaultUIStyle = "light"; //默认样式 light:白色 dark:黑色
            this.firstTouch = false; //是否第一次触摸
            this.focusedView = null; //焦点视图
            this.isPath = false; //是否路径
            this.isMobile = false; //是否移动端
            this.moveTo = false;
            this.offsetX = 0; //横向偏移
            this.offsetY = 0; //纵向偏移
            this.ratio = 1; //缩放比例
            this.scaleFactorX = 1; //横向缩放比例
            this.scaleFactorY = 1; //纵向缩放比例
            this.secondTouch = false; //是否第二次触摸
            this.systemFont = "Arial"; //系统字体
            this.touchDownView = null; //触摸的视图
            this.touchMoveView = null; //触摸移动的视图
            this.touchDownPoint = null; //触摸的坐标
            this.touchFirstPoint = new FCPoint(0, 0); //第一次触摸的点
            this.touchSecondPoint = new FCPoint(0, 0); //第二次触摸的点
            this.viewMode = 0; //视图的模式
            this.views = new Array(); //视图集合
            this.onClickGridCell = null; //点击单元格的回调
            this.onClickGridColumn = null; //点击列的回调
            this.onContainsPoint = null; //是否包含坐标点
            this.onInvalidate = null; //绘图回调
            this.onInvalidateView = null; //局部绘图回调
            this.onPaint = null; //重绘回调
            this.onPaintBorder = null; //重绘边线回调
            this.onPaintGridCell = null; //绘制单元格的回调
            this.onPaintGridColumn = null; //绘制表格列的回调
            this.onRenderViews = null; //绘制视图的回调
            this.onUpdateView = null; //更新布局的回调
        }
        /*
        * 添加线
        * x1:横坐标1
        * y1:纵坐标1
        * x2:横坐标2
        * y2:纵坐标2
        */
        addLine(x1, y1, x2, y2) {
            if (!this.moveTo) {
                this.moveTo = true;
                this.context.moveTo(Math.round((x1 + this.offsetX) * this.scaleFactorX), Math.round((y1 + this.offsetY) * this.scaleFactorY));
            }
            this.context.lineTo(Math.round((x2 + this.offsetX) * this.scaleFactorX), Math.round((y2 + this.offsetY) * this.scaleFactorY));
        };
        /*
        * 开始路径
        */
        beginPath() {
            this.context.beginPath();
            this.isPath = true;
        };
        /*
        * 开始绘图
        * rect:区域
        */
        beginPaint(rect) {
            if(this.container){
                if(!this.context){
                    this.context = uni.createCanvasContext(this.canvas.id, this.container);
                }
            } else {
                if (!this.context) {
                    this.context = this.canvas.getContext("2d");
                }
            }
            this.moveTo = false;
            this.offsetX = 0;
            this.offsetY = 0;
        };
        /*
        * 闭合路径
        */
        closeFigure() {
            this.context.closePath();
        };
        /*
        * 关闭路径
        */
        closePath() {
            this.moveTo = false;
        };
        /*
        * 绘制线
        * color:颜色
        * width:宽度
        * style:样式
        * x1:横坐标1
        * y1:纵坐标1
        * x2:横坐标2
        * y2:纵坐标2
        */
        drawLine(color, width, style, x1, y1, x2, y2) {
            width = Math.min(this.scaleFactorX, this.scaleFactorY) * width;
            this.context.beginPath();
            this.context.strokeStyle = convertColor(color);
            this.context.lineWidth = width;
            if (this.context.lineWidth < 1) {
                this.context.lineWidth = 1;
            }
            if (style != 0) {
                this.context.setLineDash(style);
            }
            this.context.moveTo(Math.round((x1 + this.offsetX) * this.scaleFactorX), Math.round((y1 + this.offsetY) * this.scaleFactorY));
            this.context.lineTo(Math.round((x2 + this.offsetX) * this.scaleFactorX), Math.round((y2 + this.offsetY) * this.scaleFactorY));
            this.context.stroke();
            if (style != 0) {
                this.context.setLineDash([]);
            }
        };
        /*
        * 绘制路径
        * color:颜色
        * width:宽度
        * style:样式
        */
        drawPath(color, width, style) {
            width = Math.min(this.scaleFactorX, this.scaleFactorY) * width;
            if (style != 0) {
                this.context.setLineDash(style);
            }
            this.context.strokeStyle = convertColor(color);
            this.context.lineWidth = width;
            if (this.context.lineWidth < 1) {
                this.context.lineWidth = 1;
            }
            this.context.stroke();
            if (style != 0) {
                this.context.setLineDash([]);
            }
        };
        /*
        * 绘制图片
        * left:左侧坐标
        * top:上方坐标
        * right:右侧坐标
        * bottom:下方坐标
        */
        drawImage(image, left, top, right, bottom) {
            let w = right - left;
            let h = bottom - top;
            try{
                this.context.drawImage(image, Math.round((left + this.offsetX) * this.scaleFactorX), Math.round((top + this.offsetY) * this.scaleFactorY), Math.round(w * this.scaleFactorX), Math.round(h * this.scaleFactorY));
            }catch(err){

            }
        };
       /*
        * 绘制多边形
        * color:颜色
        * width:宽度
        * style:样式
        */
        drawPolygon(color, width, style, apt) {
            if(apt.length > 1){
                width = Math.min(this.scaleFactorX, this.scaleFactorY) * width;
                if (style) {
                    this.context.setLineDash(style);
                }
                this.context.strokeStyle = convertColor(color);
                if (this.context.lineWidth < 1) {
                    this.context.lineWidth = 1;
                }
                this.context.beginPath();
                for(let i = 0; i < apt.length; i++){
                    let x = apt[i].x;
                    let y = apt[i].y;
                    x = x + this.offsetX;
                    y = y + this.offsetY;
                    if (this.scaleFactorX != 1 || this.scaleFactorY != 1){
                        x = this.scaleFactorX * x;
                        y = this.scaleFactorY * y;
                    }
                    if (i == 0){
                        this.context.moveTo(Math.round(x), Math.round(y));
                    }else{
                        this.context.lineTo(Math.round(x), Math.round(y));
                    }
                }
                this.context.closePath();
                this.context.stroke();
                if (style) {
                    this.context.setLineDash([]);
                }
            }
        };
        /*
        * 绘制椭圆
        * color:颜色
        * width:宽度
        * style:样式
        * left:左侧坐标
        * top:上方坐标
        * right:右侧坐标
        * bottom:下方坐标
        */
        drawEllipse(color, width, style, left, top, right, bottom) {
            width = Math.min(this.scaleFactorX, this.scaleFactorY) * width;
            let w = right - left;
            let h = bottom - top;

            if (style != 0) {
                this.context.setLineDash(style);
            }
            this.context.strokeStyle = convertColor(color);
            this.context.lineWidth = width;
            if (this.context.lineWidth < 1) {
                this.context.lineWidth = 1;
            }
            let centerX = (left + (right - left) / 2 + this.offsetX) * this.scaleFactorX;
            let centerY = (top + (bottom - top) / 2 + this.offsetY) * this.scaleFactorY;
            if (this.context.ellipse) {
                this.context.beginPath();
                this.context.ellipse(centerX, centerY, (w / 2) * this.scaleFactorX, (h / 2) * this.scaleFactorY, 0, 0, Math.PI * 2);
                this.context.stroke();
            } else {
                let radius = Math.max(w, h) / 2;
                if(radius < 1){
                    radius = 1;
                }
                this.context.save();
                this.context.translate(centerX, centerY);
                if(radius > 1){
                    if (w > h) {
                        this.context.scale(1, h / w);
                    } else if (w < h) {
                        this.context.scale(w / h, 1);
                    }
                }
                this.context.beginPath();
                this.context.arc(0, 0, radius, 0, 2 * Math.PI, false);
                this.context.stroke();
                this.context.restore();
            }
            
            if (style != 0) {
                this.context.setLineDash([]);
            }
        };
        /*
        * 绘制矩形
        * color:颜色
        * width:宽度
        * style:样式
        * left:左侧坐标
        * top:上方坐标
        * right:右侧坐标
        * bottom:下方坐标
        */
        drawRect(color, width, style, left, top, right, bottom) {
            width = Math.min(this.scaleFactorX, this.scaleFactorY) * width;
            let w = right - left;
            let h = bottom - top;
            if (style != 0) {
                this.context.setLineDash(style);
            }
            this.context.strokeStyle = convertColor(color);
            this.context.lineWidth = width;
            if (this.context.lineWidth < 1) {
                this.context.lineWidth = 1;
            }
            this.context.strokeRect(Math.round((left + this.offsetX) * this.scaleFactorX), Math.round((top + this.offsetY) * this.scaleFactorY), Math.round(w * this.scaleFactorX), Math.round(h * this.scaleFactorY));
            if (style != 0) {
                this.context.setLineDash([]);
            }
        };
        /*
        * 绘制圆角矩形
        * color:颜色
        * left:左侧坐标
        * top:上方坐标
        * right:右侧坐标
        * bottom:下方坐标
        * cornerRadius:圆角度数
        */
        drawRoundRect(color, width, style, left, top, right, bottom, cornerRadius) {
            if (cornerRadius > 0) {
                width = Math.min(this.scaleFactorX, this.scaleFactorY) * width;
                if (style != 0) {
                    this.context.setLineDash(style);
                }
                this.context.strokeStyle = convertColor(color);
                this.context.lineWidth = width;
                if (this.context.lineWidth < 1) {
                    this.context.lineWidth = 1;
                }
                let corner = cornerRadius * Math.min(this.scaleFactorX, this.scaleFactorY);
                let w = Math.round((right - left) * this.scaleFactorX);
                let h = Math.round((bottom - top) * this.scaleFactorY);
                let x = (left + this.offsetX) * this.scaleFactorX;
                let y = (top + this.offsetY) * this.scaleFactorY;
                this.context.beginPath();
                this.context.moveTo(x + corner, y);
                this.context.arcTo(x + w, y, x + w, y + h, corner);
                this.context.arcTo(x + w, y + h, x, y + h, corner);
                this.context.arcTo(x, y + h, x, y, corner);
                this.context.arcTo(x, y, x + corner, y, corner);
                this.context.stroke();
                if (style != 0) {
                    this.context.setLineDash([]);
                }
            } else {
                this.drawRect(color, width, style, left, top, right, bottom);
            }
        };
        /*
        * 绘制文字
        * text:文字
        * color:颜色
        * font:字体
        * x:横坐标
        * y:纵坐标
        */
        drawText(text, color, font, x, y) {
            if (text && text.length != 0 && font) {
                let strs = font.split(',');
                let fontFamily = strs[0];
                if (fontFamily == "Default") {
                    fontFamily = this.systemFont;
                }
                let sFont = parseInt(strs[1]) + "px " + fontFamily;
                if (this.scaleFactorX != 1 || this.scaleFactorY != 1) {
                    sFont = parseInt(Math.min(this.scaleFactorX, this.scaleFactorY) * parseFloat(strs[1])) + "px " + fontFamily;
                }
                for (let i = 2; i < strs.length; i++) {
                    let iStr = strs[i].toLowerCase();
                    if (iStr == "bold" || iStr == "italic") {
                        sFont = iStr + " " + sFont;
                    }
                }
                this.context.font = sFont;
                this.context.fillStyle = convertColor(color);
                this.context.textAlign = 'left';
                this.context.textBaseline = 'top';
                this.context.fillText(text, Math.round((x + this.offsetX) * this.scaleFactorX), Math.round((y + this.offsetY) * this.scaleFactorY));
            }
        };
        /*
        * 结束绘图
        */
        endPaint() {
            if(this.container){
                this.context.draw();
            }
        };
        /*
        * 填充路径
        * color:颜色
        */
        fillPath(color) {
            let fColor = convertColor(color);
            if (this.context.fillStyle != fColor) {
                this.context.fillStyle = fColor;
            }
            this.context.fill();
        };
        /*
        * 填充矩形
        * color:颜色
        * left:左侧坐标
        * top:上方坐标
        * right:右侧坐标
        * bottom:下方坐标
        */
        fillRect(color, left, top, right, bottom) {
            let w = right - left;
            let h = bottom - top;
            this.context.fillStyle = convertColor(color);
            this.context.fillRect(Math.round((left + this.offsetX) * this.scaleFactorX), Math.round((top + this.offsetY) * this.scaleFactorY), Math.round(w * this.scaleFactorX), Math.round(h * this.scaleFactorY));
        };
        /*
        * 填充圆角矩形
        * color:颜色
        * left:左侧坐标
        * top:上方坐标
        * right:右侧坐标
        * bottom:下方坐标
        * cornerRadius:圆角度数
        */
        fillRoundRect(color, left, top, right, bottom, cornerRadius) {
            if (cornerRadius > 0) {
                let w = Math.round((right - left) * this.scaleFactorX);
                let h = Math.round((bottom - top) * this.scaleFactorY);
                let x = (left + this.offsetX) * this.scaleFactorX;
                let y = (top + this.offsetY) * this.scaleFactorY;
                let corner = cornerRadius * Math.min(this.scaleFactorX, this.scaleFactorY);
                this.context.beginPath();
                this.context.moveTo(x + corner, y);
                this.context.arcTo(x + w, y, x + w, y + h, corner);
                this.context.arcTo(x + w, y + h, x, y + h, corner);
                this.context.arcTo(x, y + h, x, y, corner);
                this.context.arcTo(x, y, x + corner, y, corner);
                this.context.fillStyle = convertColor(color);
                this.context.fill();
            } else {
                this.fillRect(color, left, top, right, bottom);
            }
        };
        /*
        * 填充椭圆
        * color:颜色
        * left:左侧坐标
        * top:上方坐标
        * right:右侧坐标
        * bottom:下方坐标
        */
        fillEllipse(color, left, top, right, bottom) {
            let w = right - left;
            let h = bottom - top;
            this.context.fillStyle = convertColor(color);
            let centerX = (left + (right - left) / 2 + this.offsetX) * this.scaleFactorX;
            let centerY = (top + (bottom - top) / 2 + this.offsetY) * this.scaleFactorY;
            if (this.context.ellipse) {
                this.context.beginPath();
                this.context.ellipse(centerX, centerY, (w / 2) * this.scaleFactorX, (h / 2) * this.scaleFactorY, 0, 0, Math.PI * 2);
                this.context.fill();
            } else {
                let radius = Math.max(w, h) / 2;
                if(radius < 1){
                    radius = 1;
                }
                this.context.save();
                this.context.translate(centerX, centerY);
                if(radius > 1){
                    if (w > h) {
                        this.context.scale(1, h / w);
                    } else if (w < h) {
                        this.context.scale(w / h, 1);
                    }
                }
                this.context.beginPath();
                this.context.arc(0, 0, radius, 0, 2 * Math.PI, false);
                this.context.fill();
                this.context.restore();
            }
        };
        /*
	* 填充多边形
	* color:颜色
	* width:宽度
	* style:样式
	*/
	fillPolygon(color, apt) {
		if(apt.length > 1){
			this.context.beginPath();
			for(let i = 0; i < apt.length; i++){
				let x = apt[i].x;
				let y = apt[i].y;
				x = x + this.offsetX;
				y = y + this.offsetY;
				if (this.scaleFactorX != 1 || this.scaleFactorY != 1){
					x = this.scaleFactorX * x;
					y = this.scaleFactorY * y;
				}
				if (i == 0){
					this.context.moveTo(Math.round(x), Math.round(y));
				}else{
					this.context.lineTo(Math.round(x), Math.round(y));
				}
			}
			this.context.fillStyle = convertColor(color);
			this.context.closePath();
			this.context.fill();
		}
	};
        /*
        * 裁剪
        * left:左侧坐标
        * top:上方坐标
        * right:右侧坐标
        * bottom:下方坐标
        */
        setClip(left, top, right, bottom) {
            let w = right - left;
            let h = bottom - top;
            this.context.beginPath();
            this.context.rect(Math.round((left + this.offsetX) * this.scaleFactorX), Math.round((top + this.offsetY) * this.scaleFactorY), Math.round(w * this.scaleFactorX), Math.round(h * this.scaleFactorY));
            this.context.clip();
        };

        /*
        * 设置偏移量
        * offsetX:横向偏移
        * offsetY:纵向偏移
        */
        setOffset(offsetX, offsetY) {
            this.offsetX = offsetX;
            this.offsetY = offsetY;
        };
        /*
        * 获取字体大小
        * text:文字
        * font:字体
        */
        textSize(text, font) {
            if (text && text.length != 0 && font) {
                let strs = font.split(',');
                let fontFamily = strs[0];
                if (fontFamily == "Default") {
                    fontFamily = this.systemFont;
                }
                let sFont = parseInt(strs[1]) + "px " + fontFamily;
                for (let i = 2; i < strs.length; i++) {
                    let iStr = strs[i].toLowerCase();
                    if (iStr == "bold" || iStr == "italic") {
                        sFont = iStr + " " + sFont;
                    }
                }
                this.context.font = sFont;
                this.context.textAlign = 'left';
                this.context.textBaseline = 'top';
                let metrics = this.context.measureText(text);
                if(this.container){
                    return new FCSize(metrics.width, parseInt(strs[1]));
                }else{
                    let actualHeight = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;
                    if(!actualHeight || actualHeight <= 0){
                        return new FCSize(metrics.width, parseInt(strs[1]));
                    }else{
                        let tSize = new FCSize(metrics.width, actualHeight);
                        return tSize;
                    }
                }
            } else {
                return new FCSize(0, 0);
            }
        };
        /*
        * 保存状态
        */
        save() {
            this.context.save();
        };
        /*
        * 恢复状态
        */
        restore() {
            this.context.restore();
        };
        /*
        * 绘制文字，超过范围的内容用...表示
        * text:文字
        * color:颜色
        * font:字体
        * left:左侧坐标
        * top:上方坐标
        * right:右侧坐标
        * bottom:下方坐标
        */
        drawTextAutoEllipsis(text, color, font, left, top, right, bottom) {
            if (text && text.length != 0) {
                let tSize = this.textSize(text, font);
                if (tSize.cx < right - left) {
                    this.drawText(text, color, font, left, top);
                } else {
                    if (tSize.cx > 0) {
                        let subLen = 3;
                        while (true) {
                            let newLen = text.length - subLen;
                            if (newLen > 0) {
                                let newText = text.substring(0, newLen) + "...";
                                tSize = this.textSize(newText, font);
                                if (tSize.cx < right - left) {
                                    this.drawText(newText, color, font, left, top);
                                    break;
                                } else {
                                    subLen += 3;
                                }
                            } else {
                                break;
                            }
                        }
                    }
                }
            }
        };
    };
        
    /*
    * 基础视图
    */
    class FCView {
        // 构造函数
        constructor() {
            this.allowDrag = false; //是否允许拖动
            this.align = "left"; //横向布局
            this.allowDragScroll = false; //是否允许拖动滚动
            this.backColor = null; //背景色
            this.backImage = null; //背景图片
            this.borderColor = null; //边线色
            this.clipRect = null; //裁剪区域
            this.cornerRadius = 0; //圆角
            this.displayOffset = true; //是否显示偏移量
            this.dock = "none"; //悬浮状态
            this.downScrollHButton = false; //是否按下横向滚动条
            this.downScrollVButton = false; //是否按下纵向滚动条
            this.exAttributes = new Map(); //额外属性
            this.enabled = true; //是否可用
            this.font = "Default,12"; //字体
            this.hoveredColor = null; //鼠标悬停时的颜色
            this.image = null; //图片
            this.input = null; //包含的原生组件
            this.location = new FCPoint(0, 0); //坐标
            this.maximumSize = new FCSize(0, 0); //大小
            this.paint = null; //绘图对象
            this.parent = null; //父视图
            this.pushedColor = "rgb(200,200,200)"; //鼠标按下时的颜色
            this.resizePoint = -1; //调整尺寸的点
            this.scrollV = 0; //纵向滚动
            this.scrollH = 0; //横向滚动
            this.scrollSize = 8; //滚动条的大小
            this.showHScrollBar = false; //是否显示横向滚动条
            this.showVScrollBar = false; //是否显示纵向滚动条
            this.scrollBarColor = "rgb(200,200,200)"; //滚动条的颜色
            this.scrollBarHoveredColor = "rgb(42,138,195)"; //滚动条悬停的颜色
            this.size = new FCSize(0, 0); //大小
            this.startScrollH = 0; //开始滚动的值
            this.startScrollV = 0; //结束滚动的值
            this.startPoint = new FCPoint(); //起始点
            this.startRect = new FCRect(); //移动开始时的视图矩形
            this.tag = null; //数据
            this.topMost = false; //是否置顶
            this.text = null; //文字
            this.textColor = null; //前景色
            this.touchDownTime = 0; //鼠标按下的时间
            this.views = new Array(); //子视图
            this.viewName = null; //名称
            this.visible = true; //可见性
            this.verticalAlign = "top"; //纵向布局
        };
    };

    /*
    * 表格列
    */
    class FCGridColumn {
        constructor() {
            this.backColor = "rgb(200,200,200)"; //背景色
            this.borderColor = "rgb(150,150,150)"; //边线颜色
            this.bounds = new FCRect(); //区域
            this.font = "Default,12"; //字体
            this.frozen = false; //是否冻结
            this.index = -1; //索引
            this.sort = "none"; //排序模式
            this.text = ""; //文字
            this.textColor = "rgb(50,50,50)"; //文字颜色
            this.visible = true; //是否可见
            this.width = 120; //宽度
            this.widthStr = ""; //宽度字符串
        }
    };

    /*
    * 表格单元格
    */
    class FCGridCell {
        constructor() {
            this.backColor = "rgb(255,255,255)"; //背景色
            this.borderColor = "rgb(150,150,150)"; //边线颜色
            this.column = null; //所在列
            this.font = "Default,12"; //字体
            this.textColor = "rgb(0,0,0)"; //文字颜色
            this.value = null; //值
        }
    };

    /*
    * 表格行
    */
    class FCGridRow {
        constructor() {
            this.cells = new Array(); //单元格
            this.index = -1; //行的索引
            this.selected = false; //是否选中
            this.visible = true; //是否可见
        }
    };

    /*
    * 表格
    */
    class FCGrid extends FCView {
        // 构造函数
        constructor() {
            super();
            super.allowDragScroll = true; //是否允许拖动滚动
            this.columns = new Array(); //列
            this.headerHeight = 30; //头部高度
            this.rows = new Array(); //行
            this.rowHeight = 30; //行高
            super.showHScrollBar = true; //是否显示横向滚动条
            super.showVScrollBar = true; //是否显示横向滚动条
            this.selectedRowColor = "rgb(125,125,125)"; //选中行的颜色
            super.viewType = "grid"; //类型
        }
    };

    /*
    * 添加顶层视图
    * view:视图
    * paint:绘图对象
    */
    let addView = function (view, paint) {
        view.paint = paint;
        paint.views.push(view);
    };
    /*
    * 获取点击位置
    * evt:事件
    * canvas:图层
    * ratio:比例
    */
    let getTouchPosition = function (evt, canvas, paint) {
        let style = window.getComputedStyle(canvas, null);
        //宽高
        let cssWidth = parseFloat(style["width"]);
        let cssHeight = parseFloat(style["height"]);
        //各个方向的边框长度
        let borderLeft = parseFloat(style["border-left-width"]);
        let borderTop = parseFloat(style["border-top-width"]);
        let paddingLeft = parseFloat(style["padding-left"]);
        let paddingTop = parseFloat(style["padding-top"]);

        let scaleX = canvas.width / cssWidth; // 水平方向的缩放因子
        let scaleY = canvas.height / cssHeight; // 垂直方向的缩放因子
        let x = evt.clientX;
        let y = evt.clientY;

        let rect = canvas.getBoundingClientRect();
        x -= (rect.left + borderLeft + paddingLeft); // 去除 borderLeft paddingLeft 后的坐标
        y -= (rect.top + borderTop + paddingTop); // 去除 borderLeft paddingLeft 后的坐标

        x *= scaleX; // 修正水平方向的坐标
        y *= scaleY; // 修正垂直方向的坐标
        x /= paint.ratio;
        y /= paint.ratio;
        x /= paint.scaleFactorX;
        y /= paint.scaleFactorY;
        return { x, y };
    };

    /*
    * 重绘视图
    * views:视图集合
    * paint:绘图对象
    * rect:区域
    */
    let renderViews = function (views, paint, rect) {
        let viewsSize = views.length;
        for (let i = 0; i < viewsSize; i++) {
            let view = views[i];
            let drawRect = new FCRect(0, 0, view.size.cx, view.size.cy);
            paint.setOffset(0, 0);
            paint.setClip(drawRect.left, drawRect.top, drawRect.right, drawRect.bottom);
            if (paint.onPaint) {
                paint.onPaint(view, paint, drawRect);
            } 
            if (paint.onPaintBorder) {
                paint.onPaintBorder(view, paint, drawRect);
            } 
        }
    };

    /*
    * 全局刷新方法
    * paint:绘图对象
    */
    let invalidate = function (paint) {
        let drawViews = paint.views;
        if (paint.onInvalidate) {
            paint.onInvalidate(paint);
        } else {
            paint.beginPaint(null);
            let drawRect = new FCRect(0, 0, (paint.canvas.width / paint.ratio / paint.scaleFactorX), (paint.canvas.height / paint.ratio / paint.scaleFactorY));
            if (paint.onRenderViews) {
                paint.onRenderViews(drawViews, paint, drawRect);
            } else {
                renderViews(drawViews, paint, drawRect);
            }
            paint.endPaint();
        }
    };

    /*
    * 刷新视图方法
    * view:视图
    */
    let invalidateView = function (view) {
        invalidate(view.paint);
    };
        
    /*
    * 更新布局状态
    * views:视图集合
    */
    let updateViewDefault = function (views) {
        for (let i = 0; i < views.length; i++) {
            let view = views[i];
            if (view.dock == "fill") {
                let paint = view.paint;
                view.size = new FCSize((paint.canvas.width / paint.ratio / paint.scaleFactorX), (paint.canvas.height / paint.ratio / paint.scaleFactorY));
            }
            if (view.views) {
                updateViewDefault(view.views);
            }
        }
    };

    /*
    * 添加鼠标按下的方法
    * canvas:图层
    * callBack:回调函数
    */
    let addMouseDownEvent = function (canvas, paint, callBack) {
        canvas.onmousedown = function (evt) {
            if (!paint.isMobile) {
                let mp = getTouchPosition(evt, canvas, paint);
                paint.cancelClick = false;
                paint.touchDownPoint = mp;
                paint.touchDownView = gList;
                if (paint.touchDownView) {
                    paint.focusedView = paint.touchDownView;
                    let cmp = new FCPoint(mp.x, mp.y);
                    if (callBack) {
                        if (evt.button == 2) {
                            callBack(paint.touchDownView, cmp, 2, 1, 0);
                        } else {
                            callBack(paint.touchDownView, cmp, 1, 1, 0);
                        }
                    } 
                }
            }
        };
    };

    /*
    * 添加鼠标移动的方法
    * canvas:图层
    * callBack:回调函数
    */
    let addMouseMoveEvent = function (canvas, paint, callBack) {
        canvas.onmousemove = function (evt) {
            if (evt.buttons == 0) {
                paint.touchDownView = null;
            }
            if (!paint.isMobile) {
                let mp = getTouchPosition(evt, canvas, paint);
                if (paint.touchDownView) {
                    paint.touchMoveView = paint.touchDownView;
                    let cmp = new FCPoint(mp.x, mp.y);
                    if (callBack) {
                        callBack(paint.touchDownView, cmp, 1, 1, 0);
                    } 
                }
                else {
                    let view = gList;
                    let cmp = new FCPoint(mp.x, mp.y);
                    if (view) {
                        oldMouseMoveView = paint.touchMoveView
                        paint.touchMoveView = view;
                        if (oldMouseMoveView && oldMouseMoveView != view) {
                            invalidateView(oldMouseMoveView);
                        }
                        if (callBack) {
                            callBack(view, cmp, 0, 0, 0);
                        } 
                    }
                }
            }
        };
    };

    /*
    * 添加鼠标滚动的方法
    * canvas:图层
    * callBack:回调函数
    */
    let addMouseWheelEvent = function (canvas, paint, callBack) {
        canvas.addEventListener("DOMMouseScroll", function (evt) {
            if (!paint.isMobile) {
                let mp = getTouchPosition(evt, canvas, paint);
                let view = gList;
                if (view) {
                    let cmp = new FCPoint(mp.x, mp.y);
                    let delta = evt.detail;
                    if (callBack) {
                        callBack(view, cmp, 0, 0, delta);
                    } 
                }
                if (view && view.allowDragScroll) {
                    evt.preventDefault && evt.preventDefault();
                    evt.returnValue = false;
                    evt.stopPropagation && evt.stopPropagation();
                }
            }
            return false;
        }, false);
        //图层鼠标移动事件
        canvas.onmousewheel = function (evt) {
            if (!paint.isMobile) {
                let mp = getTouchPosition(evt, canvas, paint);
                let view = gList;
                if (view) {
                    let cmp = new FCPoint(mp.x, mp.y);
                    let delta = evt.deltaY;
                    if (callBack) {
                        callBack(view, cmp, 0, 0, delta);
                    } 
                }
                if (view && view.allowDragScroll) {
                    evt.preventDefault && evt.preventDefault();
                    evt.returnValue = false;
                    evt.stopPropagation && evt.stopPropagation();
                }
            }
            return false;
        };
    };

    /*
    * 添加鼠标抬起的方法
    * canvas:图层
    * callBack:回调函数
    */
    let addMouseUpEvent = function (canvas, paint, callBack, clickCallBack) {
        canvas.onmouseup = function (evt) {
            if (!paint.isMobile) {
                let mp = getTouchPosition(evt, canvas, paint);
                if (paint.touchDownView) {
                    let cmp = new FCPoint(mp.x, mp.y);
                    let view = gList;
                    if (view != null && view == paint.touchDownView) {
                        if (!paint.cancelClick) {
                            if (clickCallBack) {
                                clickCallBack(paint.touchDownView, true, cmp, false, cmp, 1);
                            } 
                        }
                    }
                    if (paint.touchDownView) {
                        let touchDownView = paint.touchDownView;
                        paint.touchDownView = null;
                        paint.touchMoveView = null;
                        if (callBack) {
                            callBack(touchDownView, cmp, 1, 1, 0);
                        }
                    }
                }
            }
        };
    };

    /*
    * 添加触摸开始的方法
    * canvas:图层
    * callBack:回调函数
    */
    let addTouchBeginEvent = function (canvas, paint, callBack) {
        /*
        * 触摸开始方法
        * evt: 事件参数
        */
        canvas.ontouchstart = function (evt) {
            if (paint.isMobile) {
                paint.cancelClick = false;
                let mp = getTouchPosition(evt.touches[0], canvas, paint);
                paint.touchDownPoint = new FCPoint(mp.x, mp.y);
                paint.touchDownView = gList;
                if (paint.touchDownView) {
                    paint.focusedView = paint.touchDownView;
                    paint.firstTouch = false;
                    paint.secondTouch = false;
                    paint.touchFirstPoint = new FCPoint();
                    paint.touchSecondPoint = new FCPoint();
                    if (evt.touches.length >= 1) {
                        paint.firstTouch = true;
                        paint.touchFirstPoint = getTouchPosition(evt.touches[0], canvas, paint);
                    }
                    if (evt.touches.length >= 2) {
                        paint.secondTouch = true;
                        paint.touchSecondPoint = getTouchPosition(evt.touches[1], canvas, paint);
                    }
                    if (callBack) {
                        callBack(paint.touchDownView, paint.firstTouch, paint.touchFirstPoint, paint.secondTouch, paint.touchSecondPoint);
                    } 
                }
            }
        };
    };

    /*
    * 添加触摸移动的方法
    * canvas:图层
    * callBack:回调函数
    */
    let addTouchMoveEvent = function (canvas, paint, callBack) {
        canvas.ontouchmove = function (evt) {
            if (paint.isMobile) {
                if (paint.touchDownView) {
                    paint.firstTouch = false;
                    paint.secondTouch = false;
                    paint.touchFirstPoint = new FCPoint();
                    paint.touchSecondPoint = new FCPoint();
                    let mp = getTouchPosition(evt.touches[0], canvas, paint);
                    if (evt.touches.length >= 1) {
                        paint.firstTouch = true;
                        paint.touchFirstPoint = getTouchPosition(evt.touches[0], canvas, paint);
                    }
                    if (evt.touches.length >= 2) {
                        paint.secondTouch = true;
                        paint.touchSecondPoint = getTouchPosition(evt.touches[1], canvas, paint);
                    }
                    if (callBack) {
                        callBack(paint.touchDownView, paint.firstTouch, paint.touchFirstPoint, paint.secondTouch, paint.touchSecondPoint);
                    } 
                    paint.touchDownPoint = mp;
                    if (paint.touchDownView && paint.touchDownView.allowDragScroll) {
                        evt.preventDefault && evt.preventDefault();
                        evt.returnValue = false;
                        evt.stopPropagation && evt.stopPropagation();
                    }
                }
            }
            return false;
        };
    };

    /*
    * 添加触摸结束的方法
    * canvas:图层
    * callBack:回调函数
    */
    let addTouchEndEvent = function (canvas, paint, callBack, clickCallBack) {
        canvas.ontouchend = function (evt) {
            if (paint.isMobile) {
                if (paint.touchDownView) {
                    let touchDownView = paint.touchDownView;
                    let mp = paint.touchDownPoint;
                    let view = gList;
                    if (view != null && view == paint.touchDownView) {
                        let cmp = new FCPoint(mp.x, mp.y);
                        if (clickCallBack) {
                            clickCallBack(paint.touchDownView, true, cmp, false, cmp, 1);
                        } 
                    }
                    paint.touchDownView = null;
                    if (callBack) {
                        callBack(touchDownView, paint.firstTouch, paint.touchFirstPoint, paint.secondTouch, paint.touchSecondPoint);
                    } 
                }
            }
        };
    };

    /*
    * 绘制表格
    * grid:表格
    * paint:绘图对象
    * clipRect:裁剪区域
    */
    let drawGrid = function (grid, paint, clipRect) {
        let cTop = -grid.scrollV + grid.headerHeight;
        //绘制行
        let colLeft = 0;
        for (let i = 0; i < grid.columns.length; i++) {
            if (grid.columns[i].widthStr.length > 0) {
                let newWidthStr = grid.columns[i].widthStr.replace("%", "");
                grid.columns[i].width = Number(newWidthStr) * grid.size.cx / 100;
            }
            let colRect = new FCRect(colLeft, 0, colLeft + grid.columns[i].width, grid.headerHeight);
            grid.columns[i].bounds = colRect;
            grid.columns[i].index = i;
            colLeft += grid.columns[i].width;
        }
        for (let i = 0; i < grid.rows.length; i++) {
            let row = grid.rows[i];
            row.index = i;
            if (row.visible) {
                let rowHeight = grid.rowHeight;
                if (!paint.isMobile && grid.size.cx > 500 && i < 2) {
                    rowHeight = 50;
                }
                let rTop = cTop, rBottom = cTop + rowHeight;
                if (rBottom >= 0 && cTop <= grid.size.cy) {
                    for (let j = 0; j < row.cells.length; j++) {
                        let cell = row.cells[j];
                        let gridColumn = cell.column;
                        if (!gridColumn) {
                            gridColumn = grid.columns[j];
                        }
                        if (gridColumn.visible) {
                            if (!gridColumn.frozen) {
                                let cellWidth = gridColumn.width;
                                let cellHeight = rowHeight;
                                let cRect = new FCRect(gridColumn.bounds.left - grid.scrollH, rTop, gridColumn.bounds.left + cellWidth - grid.scrollH, rTop + cellHeight);
                                if (cRect.right >= 0 && cRect.left < grid.size.cx) {
                                    if (paint.onPaintGridCell) {
                                        paint.onPaintGridCell(grid, row, gridColumn, cell, paint, cRect.left, cRect.top, cRect.right, cRect.bottom);
                                    } 
                                }
                            }
                        }
                    }
                }
                if (cTop > grid.size.cy) {
                    break;
                }
                cTop += rowHeight;
            }
        }
    };

    /*
    * 绘制表格的滚动条
    * grid:表格
    * paint:绘图对象
    * clipRect:裁剪区域
    */
    let drawGridScrollBar = function (grid, paint, clipRect) {
        if (grid.headerHeight > 0) {
            let cLeft = -grid.scrollH;
            //绘制列
            for (let i = 0; i < grid.columns.length; i++) {
                let gridColumn = grid.columns[i];
                if (grid.columns[i].visible) {
                    if (!gridColumn.frozen) {
                        if (paint.onPaintGridColumn) {
                            paint.onPaintGridColumn(grid, grid.columns[i], paint, cLeft, 0, cLeft + gridColumn.width, grid.headerHeight);
                        } 
                    }
                    cLeft += gridColumn.width;
                }
            }
        }
        if (paint.isMobile) {
            if (paint.touchDownView == grid) {
            } else if (g_dragScrollView_Grid == grid && g_scrollAddSpeed_Grid != 0) {
            } else {
                return;
            }
        }
        if (grid.showHScrollBar) {
            let contentWidth = getGridContentWidth(grid);
            if (contentWidth > 0 && contentWidth > grid.size.cx) {
                let sLeft = grid.scrollH / contentWidth * grid.size.cx;
                let sRight = (grid.scrollH + grid.size.cx) / contentWidth * grid.size.cx;
                if (sRight - sLeft < grid.scrollSize) {
                    sRight = sLeft + grid.scrollSize;
                }
                if (paint.touchMoveView == grid && (grid.hoverScrollHButton || grid.downScrollHButton)) {
                    paint.fillRect(grid.scrollBarHoveredColor, sLeft, grid.size.cy - grid.scrollSize, sRight, grid.size.cy);
                } else {
                    paint.fillRect(grid.scrollBarColor, sLeft, grid.size.cy - grid.scrollSize, sRight, grid.size.cy);
                }
            }
        }
        if (grid.showVScrollBar) {
            let contentHeight = getGridContentHeight(grid);
            if (contentHeight > 0 && contentHeight > grid.size.cy - grid.headerHeight) {
                let sTop = grid.headerHeight + grid.scrollV / contentHeight * (grid.size.cy - grid.headerHeight - grid.scrollSize);
                let sBottom = sTop + ((grid.size.cy - grid.headerHeight - grid.scrollSize)) / contentHeight * (grid.size.cy - grid.headerHeight - grid.scrollSize);
                if (sBottom - sTop < grid.scrollSize) {
                    sBottom = sTop + grid.scrollSize;
                }
                if (paint.touchMoveView == grid && (grid.hoverScrollVButton || grid.downScrollVButton)) {
                    paint.fillRect(grid.scrollBarHoveredColor, grid.size.cx - grid.scrollSize, sTop, grid.size.cx, sBottom);
                } else {
                    paint.fillRect(grid.scrollBarColor, grid.size.cx - grid.scrollSize, sTop, grid.size.cx, sBottom);
                }
            }
        }
    };

    /*
    * 获取内容的宽度
    * grid:表格
    */
    let getGridContentWidth = function (grid) {
        return grid.size.cx;
    };

    /*
    * 获取内容的高度
    * grid:表格
    */
    let getGridContentHeight = function (grid) {
        let cHeight = 0;
        for (let i = 0; i < grid.rows.length; i++) {
            if (grid.rows[i].visible) {
                cHeight += grid.rowHeight;
            }
        }
        return cHeight;
    };

    /*
    * 表格的鼠标移动方法
    * grid: 表格
    * firstTouch:是否第一次触摸
    * firstPoint:第一次触摸的坐标
    * secondTouch:是否第二次触摸
    * secondPoint:第二次触摸的坐标
    */
    let touchMoveGrid = function (grid, firstTouch, firstPoint, secondTouch, secondPoint) {
        grid.hoverScrollHButton = false;
        grid.hoverScrollVButton = false;
        let mp = firstPoint;
        if (firstTouch) {   
            if (grid.showHScrollBar || grid.showVScrollBar) {
                if (grid.downScrollHButton) {
                    let contentWidth = getGridContentWidth(grid);
                    let subX = (mp.x - grid.startPoint.x) / grid.size.cx * contentWidth;
                    let newScrollH = grid.startScrollH + subX;
                    if (newScrollH < 0) {
                        newScrollH = 0;
                    } else if (newScrollH > contentWidth - grid.size.cx) {
                        newScrollH = contentWidth - grid.size.cx;
                    }
                    grid.scrollH = newScrollH;
                    grid.paint.cancelClick = true;
                    return;

                } else if (grid.downScrollVButton) {
                    let contentHeight = getGridContentHeight(grid);
                    let subY = (mp.y - grid.startPoint.y) / (grid.size.cy - grid.headerHeight - grid.scrollSize) * contentHeight;
                    let newScrollV = grid.startScrollV + subY;
                    if (newScrollV < 0) {
                        newScrollV = 0;
                    } else if (newScrollV > contentHeight - (grid.size.cy - grid.headerHeight - grid.scrollSize)) {
                        newScrollV = contentHeight - (grid.size.cy - grid.headerHeight - grid.scrollSize);
                    }
                    grid.scrollV = newScrollV;
                    grid.paint.cancelClick = true;
                    return;
                }
            }
            if (grid.allowDragScroll) {
                let contentWidth = getGridContentWidth(grid);
                if (contentWidth > grid.size.cx - grid.scrollSize) {
                    let subX = grid.startPoint.x - mp.x;
                    let newScrollH = grid.startScrollH + subX;
                    if (newScrollH < 0) {
                        newScrollH = 0;
                    } else if (newScrollH > contentWidth - grid.size.cx) {
                        newScrollH = contentWidth - grid.size.cx;
                    }
                    grid.scrollH = newScrollH;
                    if (Math.abs(subX) > 5) {
                        grid.paint.cancelClick = true;
                    }
                }
                let contentHeight = getGridContentHeight(grid);
                if (contentHeight > grid.size.cy - grid.headerHeight - grid.scrollSize) {
                    let subY = grid.startPoint.y - mp.y;
                    let newScrollV = grid.startScrollV + subY;
                    if (newScrollV < 0) {
                        newScrollV = 0;
                    } else if (newScrollV > contentHeight - (grid.size.cy - grid.headerHeight - grid.scrollSize)) {
                        newScrollV = contentHeight - (grid.size.cy - grid.headerHeight - grid.scrollSize);
                    }
                    grid.scrollV = newScrollV;
                    if (Math.abs(subY) > 5) {
                        grid.paint.cancelClick = true;
                    }
                }
            }
        } else {
            if (grid.showHScrollBar) {
                let contentWidth = getGridContentWidth(grid);
                if (contentWidth > 0 && contentWidth > grid.size.cx - grid.scrollSize) {
                    let sLeft = grid.scrollH / contentWidth * grid.size.cx;
                    let sRight = (grid.scrollH + grid.size.cx) / contentWidth * grid.size.cx;
                    if (sRight - sLeft < grid.scrollSize) {
                        sRight = sLeft + grid.scrollSize;
                    }
                    if (mp.x >= sLeft && mp.x <= sRight && mp.y >= grid.size.cy - grid.scrollSize && mp.y <= grid.size.cy) {
                        grid.hoverScrollHButton = true;
                        return;
                    } else {
                        grid.hoverScrollHButton = false;
                    }
                }
            }
            if (grid.showVScrollBar) {
                let contentHeight = getGridContentHeight(grid);
                if (contentHeight > 0 && contentHeight > grid.size.cy - grid.headerHeight - grid.scrollSize) {
                    let sTop = grid.headerHeight + grid.scrollV / contentHeight * (grid.size.cy - grid.headerHeight - grid.scrollSize);
                    let sBottom = grid.headerHeight + (grid.scrollV + (grid.size.cy - grid.headerHeight - grid.scrollSize)) / contentHeight * (grid.size.cy - grid.headerHeight - grid.scrollSize);
                    if (sBottom - sTop < grid.scrollSize) {
                        sBottom = sTop + grid.scrollSize;
                    }
                    if (mp.x >= grid.size.cx - grid.scrollSize && mp.x <= grid.size.cx && mp.y >= sTop && mp.y <= sBottom) {
                        grid.hoverScrollVButton = true;
                        return;
                    } else {
                        grid.hoverScrollVButton = false;
                    }
                }
            }
        }
    };
        
    /*
    * 表格的鼠标按下方法
    * grid: 表格
    * firstTouch:是否第一次触摸
    * firstPoint:第一次触摸的坐标
    * secondTouch:是否第二次触摸
    * secondPoint:第二次触摸的坐标
    * clicks:点击次数
    */
    let touchDownGrid = function (grid, firstTouch, firstPoint, secondTouch, secondPoint, clicks) {
        let mp = firstPoint;
        grid.touchDownTime = new Date().getTime()
        grid.startPoint = mp;
        grid.downScrollHButton = false;
        grid.downScrollVButton = false;
        grid.hoverScrollHButton = false;
        grid.hoverScrollVButton = false;
        g_dragScrollView_Grid = null;
        g_scrollAddSpeed_Grid = 0;
        g_scrollDirection_Grid = 0;
        if (grid.showHScrollBar) {
            let contentWidth = getGridContentWidth(grid);
            if (contentWidth > 0 && contentWidth > grid.size.cx - grid.scrollSize) {
                let sLeft = grid.scrollH / contentWidth * grid.size.cx;
                let sRight = (grid.scrollH + grid.size.cx) / contentWidth * grid.size.cx;
                if (sRight - sLeft < grid.scrollSize) {
                    sRight = sLeft + grid.scrollSize;
                }
                if (mp.x >= sLeft && mp.x <= sRight && mp.y >= grid.size.cy - grid.scrollSize && mp.y <= grid.size.cy) {
                    grid.downScrollHButton = true;
                    grid.startScrollH = grid.scrollH;
                    return;
                }
            }
        }
        if (grid.showVScrollBar) {
            let contentHeight = getGridContentHeight(grid);
            if (contentHeight > 0 && contentHeight > grid.size.cy - grid.headerHeight - grid.scrollSize) {
                let sTop = grid.headerHeight + grid.scrollV / contentHeight * (grid.size.cy - grid.headerHeight - grid.scrollSize);
                let sBottom = grid.headerHeight + (grid.scrollV + (grid.size.cy - grid.headerHeight - grid.scrollSize)) / contentHeight * (grid.size.cy - grid.headerHeight - grid.scrollSize);
                if (sBottom - sTop < grid.scrollSize) {
                    sBottom = sTop + grid.scrollSize;
                }
                if (mp.x >= grid.size.cx - grid.scrollSize && mp.x <= grid.size.cx && mp.y >= sTop && mp.y <= sBottom) {
                    grid.downScrollVButton = true;
                    grid.startScrollV = grid.scrollV;
                    return;
                }
            }
        }
        if (grid.allowDragScroll) {
            grid.startScrollH = grid.scrollH;
            grid.startScrollV = grid.scrollV;
        }
        let colLeft = 0;
        for (let i = 0; i < grid.columns.length; i++) {
            let colRect = new FCRect(colLeft, 0, colLeft + grid.columns[i].width, grid.headerHeight);
            grid.columns[i].bounds = colRect;
            grid.columns[i].index = i;
            colLeft += grid.columns[i].width;
        }
    };

    let g_dragScrollView_Grid = null;//正在滚动的表格
    let g_scrollAddSpeed_Grid = 0;//滚动加速
    let g_scrollDirection_Grid = 0; //滚动方向

    /*
    * 检查拖动滚动
    */
    let checkGridDragScroll = function () {
        if (g_dragScrollView_Grid) {
            let sub = parseInt(g_scrollAddSpeed_Grid / 10);
            if (sub == 0 && g_scrollAddSpeed_Grid > 1) {
                sub = 1;
            } else if (sub == 0 && g_scrollAddSpeed_Grid < -1) {
                sub = -1;
            }
            g_scrollAddSpeed_Grid -= sub;
            if (sub == 0) {
                let viewCache = g_dragScrollView_Grid;
                g_dragScrollView_Grid = null;
                g_scrollAddSpeed_Grid = 0;
                if (viewCache.paint) {
                    invalidateView(viewCache);
                }
            } else {
                let oldScrollV = parseInt(g_dragScrollView_Grid.scrollV + g_scrollAddSpeed_Grid);
                let oldScrollH = parseInt(g_dragScrollView_Grid.scrollH + g_scrollAddSpeed_Grid);
                if (g_scrollDirection_Grid == 0) {
                    let contentHeight = getGridContentHeight(g_dragScrollView_Grid);
                    if (contentHeight < g_dragScrollView_Grid.size.cy - g_dragScrollView_Grid.scrollSize) {
                        g_dragScrollView_Grid.scrollV = 0;
                    } else {
                        if (oldScrollV < 0) {
                            oldScrollV = 0;
                        } else if (oldScrollV > contentHeight - g_dragScrollView_Grid.size.cy + g_dragScrollView_Grid.headerHeight + g_dragScrollView_Grid.scrollSize) {
                            oldScrollV = contentHeight - g_dragScrollView_Grid.size.cy + g_dragScrollView_Grid.headerHeight + g_dragScrollView_Grid.scrollSize;
                        }
                        g_dragScrollView_Grid.scrollV = oldScrollV;
                    }
                } else {
                    let contentWidth = getGridContentWidth(g_dragScrollView_Grid);
                    if (contentWidth < g_dragScrollView_Grid.size.cx - g_dragScrollView_Grid.headerHeight - g_dragScrollView_Grid.scrollSize) {
                        g_dragScrollView_Grid.scrollH = 0;
                    } else {
                        if (oldScrollH < 0) {
                            oldScrollH = 0;
                        } else if (oldScrollH > contentWidth - g_dragScrollView_Grid.size.cx) {
                            oldScrollH = contentWidth - g_dragScrollView_Grid.size.cx;
                        }
                        g_dragScrollView_Grid.scrollH = oldScrollH;
                    }
                }
                if (g_dragScrollView_Grid.paint) {
                    invalidateView(g_dragScrollView_Grid);
                }
            }
        }
    };

    /*
    * 表格的鼠标抬起方法
    * grid: 表格
    * firstTouch:是否第一次触摸
    * firstPoint:第一次触摸的坐标
    * secondTouch:是否第二次触摸
    * secondPoint:第二次触摸的坐标
    * clicks:点击次数
    */
    let touchUpGrid = function (grid, firstTouch, firstPoint, secondTouch, secondPoint, clicks) {
        grid.hoverScrollHButton = false;
        grid.hoverScrollVButton = false;
        if (firstTouch && firstPoint && grid.startPoint && !grid.downScrollHButton && !grid.downScrollVButton) {
            if (grid.allowDragScroll) {
                let touchUpTime = new Date().getTime();
                let diff = touchUpTime - grid.touchDownTime;
                //加速滚动
                if (diff < 250) {
                    let sub1 = 100 * ((Math.abs(firstPoint.y - grid.startPoint.y)) / 20) / diff * 10;
                    let sub2 = 100 * ((Math.abs(firstPoint.x - grid.startPoint.x)) / 20) / diff * 10;
                    if ("A:" + sub1 != "A:NaN" && "A:" + sub2 != "A:NaN") {
                        if (Math.abs(sub1) > Math.abs(sub2)) {
                            if (firstPoint.y < grid.startPoint.y) {
                                g_scrollAddSpeed_Grid += sub1;
                            } else {
                                g_scrollAddSpeed_Grid -= sub1;
                            }
                            g_scrollDirection_Grid = 0;
                        } else {
                            if (firstPoint.x < grid.startPoint.x) {
                                g_scrollAddSpeed_Grid += sub2;
                            } else {
                                g_scrollAddSpeed_Grid -= sub2;
                            }
                            g_scrollDirection_Grid = 1;
                        }
                        if (Math.abs(g_scrollAddSpeed_Grid) > 0) {
                            grid.paint.cancelClick = true;
                        }
                        g_dragScrollView_Grid = grid;
                    } 
                }
            }
        }
        grid.downScrollHButton = false;
        grid.downScrollVButton = false;
        if (grid.paint.cancelClick) {
            return;
        }
        let cTop = -grid.scrollV + grid.headerHeight;
        //绘制行
        let colLeft = 0;
        for (let i = 0; i < grid.columns.length; i++) {
            let colRect = new FCRect(colLeft, 0, colLeft + grid.columns[i].width, grid.headerHeight);
            grid.columns[i].bounds = colRect;
            grid.columns[i].index = i;
            colLeft += grid.columns[i].width;
        }
        if (grid.headerHeight > 0 && firstPoint.y <= grid.headerHeight) {
            let cLeft = 0;
            cLeft = -grid.scrollH;
            for (let i = 0; i < grid.columns.length; i++) {
                let gridColumn = grid.columns[i];
                if (grid.columns[i].visible) {
                    if (!gridColumn.frozen) {
                        if (firstPoint.x >= cLeft && firstPoint.x <= cLeft + gridColumn.width) {
                            if (grid.paint && grid.paint.onClickGridColumn) {
                                grid.paint.onClickGridColumn(grid, gridColumn, firstTouch, firstPoint, secondTouch, secondPoint, clicks);
                            }
                            return;
                        }
                    }
                    cLeft += gridColumn.width;
                }
            }
        }
        for (let i = 0; i < grid.rows.length; i++) {
            let row = grid.rows[i];
            if (row.visible) {
                let rowHeight = grid.rowHeight;
                if (!grid.paint.isMobile && grid.size.cx > 500 && i < 2) {
                    rowHeight = 50;
                }
                let rTop = cTop, rBottom = cTop + rowHeight;
                if (rBottom >= 0 && cTop <= grid.size.cy) {
                    for (let j = 0; j < row.cells.length; j++) {
                        let cell = row.cells[j];
                        let gridColumn = cell.column;
                        if (!gridColumn) {
                            gridColumn = grid.columns[j];
                        }
                        if (gridColumn.visible) {
                            if (!gridColumn.frozen) {
                                let cellWidth = gridColumn.width;
                                let cellHeight = rowHeight;
                                let cRect = new FCRect(gridColumn.bounds.left - grid.scrollH, rTop, gridColumn.bounds.left + cellWidth - grid.scrollH, rTop + cellHeight);
                                if (cRect.right >= 0 && cRect.left < grid.size.cx) {
                                    if (firstPoint.x >= cRect.left && firstPoint.x <= cRect.right && firstPoint.y >= cRect.top && firstPoint.y <= cRect.bottom) {
                                        if (grid.paint && grid.paint.onClickGridCell) {
                                            grid.paint.onClickGridCell(grid, row, gridColumn, cell, firstTouch, firstPoint, secondTouch, secondPoint, clicks);
                                        }
                                        return;
                                    }
                                }
                            }
                        }
                    }
                }
                if (cTop > grid.size.cy) {
                    break;
                }
                cTop += rowHeight;
            }
        }
    };

    /*
    * 表格的鼠标滚轮方法
    * grid:表格
    * delta:滚轮值
    */
    let touchWheelGrid = function (grid, delta) {
        let oldScrollV = grid.scrollV;
        if (delta < 0) {
            oldScrollV -= 20;
        } else if (delta > 0) {
            oldScrollV += 20;
        }
        let contentHeight = getGridContentHeight(grid);
        if (contentHeight < grid.size.cy - grid.headerHeight - grid.scrollSize) {
            grid.scrollV = 0;
        } else {
            if (oldScrollV < 0) {
                oldScrollV = 0;
            } else if (oldScrollV > contentHeight - grid.size.cy + grid.headerHeight + grid.scrollSize) {
                oldScrollV = contentHeight - grid.size.cy + grid.headerHeight + grid.scrollSize;
            }
            grid.scrollV = oldScrollV;
        }
    };

    /*
    * 是否移动端
    */
    let isMobileMode = function () {
        let ua = navigator.userAgent;
        let ipad = ua.match(/(iPad).*OS\s([\d_]+)/),
            isIphone = !ipad && ua.match(/(iPhone\sOS)\s([\d_]+)/),
            isAndroid = ua.match(/(Android)\s+([\d.]+)/),
            isMobile = isIphone || isAndroid;
        return isMobile;
    };

    /*
    * 缩放Canvas
    */
    let scaleCanvas = function (paint) {
        //缩放高清模式
        if (window.devicePixelRatio && !isMobileMode()) {
            let canvas = paint.canvas;
            canvas.style.width = canvas.width + 'px';
            canvas.style.height = canvas.height + 'px';
            canvas.height = canvas.height * window.devicePixelRatio;
            canvas.width = canvas.width * window.devicePixelRatio;
            let context = canvas.getContext("2d"); //绘图上下文
            context.scale(window.devicePixelRatio, window.devicePixelRatio);
            paint.ratio = window.devicePixelRatio;
        }
    }

    let canvas = document.getElementById("exampleCanvas"); //绘图区域
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    let gPaint = new FCPaint(); //绘图对象
    gPaint.canvas = canvas;
    scaleCanvas(gPaint);
    //判断主题色
    gPaint.defaultUIStyle = "dark";
    let url = location.href;
    if (url.indexOf("color=light") != -1) {
        gPaint.defaultUIStyle = "light";
    }
    //判断移动端
    gPaint.isMobile = isMobileMode();
    if (gPaint.isMobile) {
        gPaint.scaleFactorX = 2.5;
        gPaint.scaleFactorY = 2.5;
    }
    let gList = new FCGrid();
    gList.dock = "fill";
    addView(gList, gPaint);
    if (gList.paint.defaultUIStyle == "dark") {
        gList.backColor = "rgb(0,0,0)";
        gList.borderColor = null;
        gList.textColor = "rgb(255,255,255)";
        gList.scrollBarColor = "rgb(100,100,100)";
    } else if (gList.paint.defaultUIStyle == "light") {
        gList.backColor = "rgb(230,230,230)";
        gList.borderColor = null;
        gList.textColor = "rgb(0,0,0)";
        gList.scrollBarColor = "rgb(200,200,200)";
    }
    gList.visible = true;
    gList.rowHeight = 80;
    gList.headerHeight = 50;
    let gColumn = new FCGridColumn();
    gColumn.text = "id";
    gColumn.widthStr = "100%";
    gList.columns.push(gColumn);
    if (gList.paint.defaultUIStyle == "dark") {
        gColumn.backColor = "rgb(0,0,0)";
        gColumn.borderColor = "rgb(100,100,100)";
        gColumn.textColor = "rgb(255,255,255)";
    } else if (gList.paint.defaultUIStyle == "light") {
        gColumn.backColor = "rgb(255,255,255)";
        gColumn.borderColor = "rgb(150,150,150)";
        gColumn.textColor = "rgb(0,0,0)";
    }
    let onClick = function (view, firstTouch, firstPoint, secondTouch, secondPoint, clicks) {
    };
    let onMouseDown = function (view, mp, buttons, clicks, delta) {
        touchDownGrid(view, true, mp, false, mp, clicks);
        invalidateView(view);
    };
    let onMouseWheel = function (view, mp, buttons, clicks, delta) {
        replayTick = 0;
        tick = 0;
        clickIndex = -1;
        touchWheelGrid(view, delta);
        invalidateView(view);
    };
    let onTouchBegin = function (view, firstTouch, firstPoint, secondTouch, secondPoint) {
        touchDownGrid(view, firstTouch, firstPoint, secondTouch, secondPoint, 1);
        invalidateView(view);
    };
    let onTouchMove = function (view, firstTouch, firstPoint, secondTouch, secondPoint) {
        if(firstTouch){
            replayTick = 0;
            tick = 0;
            clickIndex = -1;
            touchMoveGrid(view, firstTouch, firstPoint, secondTouch, secondPoint);
            invalidateView(view);
        }
    };
    let onTouchEnd = function (view, firstTouch, firstPoint, secondTouch, secondPoint) {
        touchUpGrid(view, firstTouch, firstPoint, secondTouch, secondPoint, 1);
        invalidateView(view);
    };
    let buttonRects = [];
    let mouseMovePoint = new FCPoint();
    let onMouseMove = function (view, mp, buttons, clicks, delta) {
        let firstTouch = false;
        mouseMovePoint = mp;
        if (buttons == 1) {
            firstTouch = true;
            replayTick = 0;
            tick = 0;
            clickIndex = -1;
            touchMoveGrid(view, firstTouch, mp, false, mp);
        }  
        invalidateView(view);
        let hoverButton = false;
        for(let i = 0; i < buttonRects.length; i++){
            let rect = buttonRects[i];
            if(mp.x >= rect.left && mp.x <= rect.right && mp.y >= rect.top && mp.y <= rect.bottom){
                hoverButton = true;
                break;
            }
        }
        if(hoverButton){
            gPaint.canvas.style.cursor = "pointer";
        }else{
            gPaint.canvas.style.cursor = "";
        }
    };
    let onMouseUp = function (view, mp, buttons, clicks, delta) {
        touchUpGrid(view, true, mp, false, mp, clicks);
        invalidateView(view);
    };
    gPaint.onUpdateView = function (views) {
        updateViewDefault(views);
    }

    //注册事件
    addMouseDownEvent(canvas, gPaint, onMouseDown);
    addMouseMoveEvent(canvas, gPaint, onMouseMove);
    addMouseWheelEvent(canvas, gPaint, onMouseWheel);
    addMouseUpEvent(canvas, gPaint, onMouseUp, onClick);
    addTouchBeginEvent(canvas, gPaint, onTouchBegin);
    addTouchMoveEvent(canvas, gPaint, onTouchMove);
    addTouchEndEvent(canvas, gPaint, onTouchEnd, onClick);

    /*
    * 重置大小
    */
    let resizeAll = function () {
        canvas.width = document.documentElement.clientWidth;
        canvas.height = document.documentElement.clientHeight;
        scaleCanvas(gPaint);
        updateViewDefault(gPaint.views);
        invalidate(gPaint);
    };

    /*
    * 监听大小改变
    */
    window.onresize = function () {
        resizeAll();
    };

    /*
    * 旋转监听
    */
    window.onorientationchange = function () {
        resizeAll();
    };

    let imagesPath = new Map();
    let images = new Map();

    /*
    * 绘制单元格
    * grid:表格
    * row:行
    * column:列
    * cell:单元格
    * paint:绘图对象
    * left:左侧坐标
    * top:上方坐标
    * right:右侧坐标
    * bottom:下方坐标
    */
    gPaint.onPaintGridCell = function (grid, row, column, cell, paint, left, top, right, bottom) {
        let width = right - left, height = bottom - top;
        let colors = new Array();
        colors.push("rgb(170, 178, 189)");
        colors.push("rgb(150, 123, 220)");
        colors.push("rgb(140, 192, 81)");
        colors.push("rgb(219, 68, 83)");
        colors.push("rgb(216, 112, 173)"); 
        colors.push("rgb(246, 187, 67)");
        colors.push("rgb(59, 174, 218)");
        colors.push("rgb(75, 137, 220)");
        colors.push("rgb(185, 63, 150)");
        colors.push("rgb(233, 87, 62)");
        if (row.index < 2) {
            if (row.index == 1) {
                let eR = grid.rowHeight * 1.5;
                if (grid.scrollV > 0) {
                    eR -= grid.scrollV / 3;
                }
                var text1s = new Array();
                var text2s = new Array();
                text1s.push("使用语言");
                text2s.push("15");
                text1s.push("支持平台");
                text2s.push("6");
                text1s.push("独立版本");
                text2s.push("50");
                if (!gPaint.isMobile && width > 500) {
                    text1s.push("研发年数");
                    text2s.push("3.5");
                    text1s.push("著作权");
                    text2s.push("7");
                    text1s.push("原创率");
                    text2s.push("99%");  
                    text1s.push("前后端");
                    text2s.push("✓");  
                    text1s.push("性能内存");
                    text2s.push("++");  
                    text1s.push("人工智能");
                    text2s.push("❖");  
                    text1s.push("多端互动");
                    text2s.push("☺");  
                }
                let tSub = 0;
                let tLeft = left + (right - left - text1s.length * (eR + tSub)) / 2;
                let avgTick = 720 / text1s.length;
                let nowIndex = parseInt((720 - tick) / avgTick);
                for (let i = 0; i < text1s.length; i++) {
                    let font1 = "Default,14";
                    let font2 = "Default,35";
                    if (!gPaint.isMobile && width > 500) {
                        font2 = "Default,28";
                    }
                    if (grid.scrollV > 0) {
                        font2 = "Default," + (35 - grid.scrollV / 5).toString();
                        if (!gPaint.isMobile && width > 500) {
                            font2 = "Default," + (28 - grid.scrollV / 5).toString();
                        }
                        font1 = "Default," + (14 - grid.scrollV / 10).toString();
                    }
                    let tSize1 = paint.textSize(text1s[i], font1);
                    let tSize2 = paint.textSize(text2s[i], font2);
                    let firstRect = new FCRect(tLeft, top - eR / 2 - 10, tLeft + eR, top + eR / 2 - 10);
                    firstRect.left += 10;
                    firstRect.top += 10;
                    firstRect.right -= 10;
                    firstRect.bottom -= 10;
                    if (!paint.isMobile && width > 500) {
                        firstRect.top += 8;
                        firstRect.bottom += 8;
                        firstRect.top += 5;
                        firstRect.bottom -= 5;
                    }
                    let bColor = "rgb(42,138,195)";
                    let bColor2 = "rgba(42,138,195,200)";
                    let corner = 10;
                    if (!gPaint.isMobile && width > 500) {
                        corner = 0;
                    }
                    if (text1s.length > 3) {
                        bColor = colors[i % colors.length];
                        bColor2 = bColor;
                    }
                    if (tick > 0 && clickIndex <= 1 &&  nowIndex == i && paint.defaultUIStyle == "dark") {
                        if (grid.paint.defaultUIStyle == "dark") {
                            if (!gPaint.isMobile && width > 500) {
                                corner = 8;
                                paint.fillRoundRect("rgba(21,24,28,150)", firstRect.left, firstRect.top, firstRect.right, firstRect.bottom, corner);
                                //paint.drawRoundRect("rgb(50,50,50)", 1, 0, firstRect.left, firstRect.top, firstRect.right, firstRect.bottom, corner);
                            }else{
                                corner = 8;
                                paint.fillRoundRect("rgb(21,24,28)", firstRect.left, firstRect.top, firstRect.right, firstRect.bottom, corner);
                            }
                            paint.drawText(text1s[i], "rgb(150,150,150)", font1, firstRect.left + (firstRect.right - firstRect.left - tSize1.cx) / 2, firstRect.top + 20 - tSize1.cy / 2);
                            paint.drawText(text2s[i], "rgb(200,200,200)", font2, firstRect.left + (firstRect.right - firstRect.left - tSize2.cx) / 2, firstRect.top + (firstRect.bottom - firstRect.top - tSize2.cy) / 2);
                        } else {
                            paint.fillRoundRect("rgb(255,255,255)", firstRect.left, firstRect.top, firstRect.right, firstRect.bottom, corner);
                            paint.drawRoundRect("rgb(200,200,200)", 1, 0, firstRect.left, firstRect.top, firstRect.right, firstRect.bottom, corner);
                            paint.drawText(text1s[i], "rgb(100,100,100)", font1, firstRect.left + (firstRect.right - firstRect.left - tSize1.cx) / 2, firstRect.top + 20 - tSize1.cy / 2);
                            paint.drawText(text2s[i], "rgb(50,50,50)", font2, firstRect.left + (firstRect.right - firstRect.left - tSize2.cx) / 2, firstRect.top + (firstRect.bottom - firstRect.top - tSize2.cy) / 2);
                        }
                    } else {
                        if (grid.paint.defaultUIStyle == "dark") {
                            if (!gPaint.isMobile && width > 500) {
                                corner = 8;
                                paint.fillRoundRect("rgba(21,24,28,150)", firstRect.left, firstRect.top, firstRect.right, firstRect.bottom, corner);
                                //paint.drawRoundRect("rgb(50,50,50)", 1, 0, firstRect.left, firstRect.top, firstRect.right, firstRect.bottom, corner);
                            }else{
                                corner = 8;
                                paint.fillRoundRect("rgb(21,24,28)", firstRect.left, firstRect.top, firstRect.right, firstRect.bottom, corner);
                            }
                            paint.drawText(text1s[i], "rgb(150,150,150)", font1, firstRect.left + (firstRect.right - firstRect.left - tSize1.cx) / 2, firstRect.top + 20 - tSize1.cy / 2);
                            paint.drawText(text2s[i], "rgb(200,200,200)", font2, firstRect.left + (firstRect.right - firstRect.left - tSize2.cx) / 2, firstRect.top + (firstRect.bottom - firstRect.top - tSize2.cy) / 2);
                        } else {
                            paint.fillRoundRect("rgb(255,255,255)", firstRect.left, firstRect.top, firstRect.right, firstRect.bottom, corner);
                            paint.drawRoundRect("rgb(200,200,200)", 1, 0, firstRect.left, firstRect.top, firstRect.right, firstRect.bottom, corner);
                            paint.drawText(text1s[i], "rgb(100,100,100)", font1, firstRect.left + (firstRect.right - firstRect.left - tSize1.cx) / 2, firstRect.top + 20 - tSize1.cy / 2);
                            paint.drawText(text2s[i], "rgb(50,50,50)", font2, firstRect.left + (firstRect.right - firstRect.left - tSize2.cx) / 2, firstRect.top + (firstRect.bottom - firstRect.top - tSize2.cy) / 2);
                        }
                    }
                    if (text1s.length > 3) {
                        paint.fillRoundRect(colors[i % colors.length], firstRect.left + (firstRect.right - firstRect.left - 25 + grid.scrollV / 10) / 2, firstRect.bottom - 15 + grid.scrollV / 20, firstRect.left + (firstRect.right - firstRect.left + 25 - grid.scrollV / 10) / 2, firstRect.bottom - 10, 2);
                    } else {
                        paint.fillRoundRect("rgb(42,138,195)", firstRect.left + (firstRect.right - firstRect.left - 25 + grid.scrollV / 10) / 2, firstRect.bottom - 15 + grid.scrollV / 20, firstRect.left + (firstRect.right - firstRect.left + 25 - grid.scrollV / 10) / 2, firstRect.bottom - 10, 2);
                    }
                    if (tick > 0 && clickIndex <= 1) {
                        let overTimes = tick;
                        if (overTimes > 360) {
                            overTimes -= 360;
                        }
                        let dRect = new FCRect(firstRect.left, firstRect.top, firstRect.right, firstRect.bottom);
                        let dWidth = Math.min(dRect.right - dRect.left, dRect.bottom - dRect.top) / 2;
                        let dInterval = 20;
                        paint.drawRect(bColor, 1, 0, dRect.left, dRect.top, dRect.right, dRect.bottom);
                        if (overTimes < 90) {
                            let fSize = (90 - overTimes) * (dWidth - dInterval) / 60;
                            let eSize = overTimes * (dWidth - dInterval) / 60;
                            paint.drawLine(bColor2, 3, 0, dRect.right - fSize, dRect.top, dRect.right, dRect.top);
                            paint.drawLine(bColor2, 3, 0, dRect.right, dRect.top, dRect.right, dRect.top + eSize);
                        }
                        else if (overTimes < 180) {
                            let fSize = (90 - (overTimes - 90)) * (dWidth - dInterval) / 60;
                            let eSize = (overTimes - 90) * (dWidth - dInterval) / 60;
                            paint.drawLine(bColor2, 3, 0, dRect.right, dRect.bottom - fSize, dRect.right, dRect.bottom);
                            paint.drawLine(bColor2, 3, 0, dRect.right, dRect.bottom, dRect.right - eSize, dRect.bottom);
                        }
                        else if (overTimes < 270) {
                            let fSize = (90 - (overTimes - 180)) * (dWidth - dInterval) / 60;
                            let eSize = (overTimes - 180) * (dWidth - dInterval) / 60;
                            paint.drawLine(bColor2, 3, 0, dRect.left, dRect.bottom, dRect.left + fSize, dRect.bottom);
                            paint.drawLine(bColor2, 3, 0, dRect.left, dRect.bottom, dRect.left, dRect.bottom - eSize);
                        }
                        else if (overTimes < 360) {
                            let fSize = (90 - (overTimes - 270)) * (dWidth - dInterval) / 60;
                            let eSize = (overTimes - 270) * (dWidth - dInterval) / 60;
                            paint.drawLine(bColor2, 3, 0, dRect.left, dRect.top, dRect.left + eSize, dRect.top);
                            paint.drawLine(bColor2, 3, 0, dRect.left, dRect.top, dRect.left, dRect.top + fSize);
                        }
                    }
                    tLeft += eR + tSub;
                }
                if (!paint.isMobile && width > 500) {

                }else{
                    let text1 = "产品列表";
                    let font3 = "Default,14";
                    let tSize1 = paint.textSize(text1, font3);
                    if (grid.paint.defaultUIStyle == "dark") {
                        paint.drawText(text1, "rgb(150,150,150)", font3, left + (right - left - tSize1.cx) / 2, bottom - tSize1.cy - tSize1.cy / 2);
                    } else {
                        paint.drawText(text1, "rgb(50,50,50)", font3, left + (right - left - tSize1.cx) / 2, bottom - tSize1.cy - tSize1.cy / 2);
                    }
                }
            }
        } else {
            if (!gPaint.isMobile && width > 500) {
                let dColor = "rgba(50,50,50)";
                let corner = 0;
                if (grid.paint.defaultUIStyle == "dark") {
                    if(gList.image2){
                        corner = 8;
                        paint.fillRoundRect("rgba(21,24,28,230)", left + 14, top + 5, right - 14, bottom - 5, corner);
                    }else{
                        corner = 8;
                        paint.fillRoundRect("rgba(21,24,28,150)", left + 14, top + 5, right - 14, bottom - 5, corner);
                    }
                } else {
                    dColor = "rgb(200,200,200)";
                    paint.fillRoundRect("rgb(240,240,240)", left + 14, top + 5, right - 14, bottom - 5, corner);
                    paint.drawRoundRect(dColor, 1, 0, left + 14, top + 5, right - 14, bottom - 5, corner)
                }
            } else {
                if (grid.paint.defaultUIStyle == "dark") {
                    paint.fillRoundRect("rgb(21,24,28)", left + 14, top + 5, right - 14, bottom - 5, 10);
                } else {
                    paint.fillRoundRect("rgb(240,240,240)", left + 14, top + 5, right - 14, bottom - 5, 10);
                }
            }
            let baseUpper = cell.text1;
            if (cell.text3 == "关于" && !gPaint.isMobile && width > 600) {
                baseUpper = "上海卷卷猫信息技术有限公司 版权所有@2023 " + baseUpper;
            }
            let font1 = "Default,15";
            let font2 = "Default,12";
            let font3 = "Default,14";
            let tSize = paint.textSize(baseUpper, font1);
            if (cell.text3 == "关于") {
                if (grid.paint.defaultUIStyle == "dark") {
                    paint.drawText(baseUpper, "rgb(200,200,200)", font1, left + (width - tSize.cx) / 2, top + (height - tSize.cy) / 2); 
                } else {
                    paint.drawText(baseUpper, "rgb(50,50,50)", font1, left + (width - tSize.cx) / 2, top + (height - tSize.cy) / 2); 
                }
                return;
            }
            let strVolume = cell.text3;
            let strPrice = cell.text4;
            let tSize2 = paint.textSize(strVolume, font2);
            let drawColor = "rgb(255,0,0)";
            let t2Size = null;
            if(cell.text2 && cell.text2.length > 0){
                t2Size = paint.textSize(cell.text2, font2);
                let midY = top + height / 2 + tSize2.cy + 2;
                let t2Rect = new FCRect(left + 26 + 4, midY - t2Size.cy / 2, left + 26 + t2Size.cx + 4, midY + t2Size.cy / 2);
                let dX = t2Rect.left;
                let dY = t2Rect.top;
                t2Rect.left -= 4;
                t2Rect.right += 4;
                t2Rect.top -= 2;
                t2Rect.bottom += 3;
                paint.fillRoundRect(colors[Number(cell.linkType) - 1], t2Rect.left, t2Rect.top, t2Rect.right, t2Rect.bottom, 4);
                paint.drawText(cell.text2, "rgb(255,255,255)", font2, dX, dY);
            }else{
                paint.fillEllipse(colors[Number(cell.linkType) - 1], left + 26, top + height / 2 + 3 + tSize2.cy - 4, left + 34, top + height / 2 + 3 + tSize2.cy + 4);
            }
            if (grid.paint.defaultUIStyle == "dark") {
                paint.drawText(baseUpper, "rgb(200,200,200)", font1, left + 26, top + height / 2 - tSize2.cy - tSize.cy / 2);
                if(cell.text2 && cell.text2.length > 0){
                    paint.drawText(strVolume, "rgb(200,200,200)", font2, left + 39 + t2Size.cx, top + height / 2 + tSize2.cy + 3 - tSize2.cy / 2);
                }else{
                    paint.drawText(strVolume, "rgb(200,200,200)", font2, left + 39, top + height / 2 + tSize2.cy + 3 - tSize2.cy / 2);
                }
            } else {
                paint.drawText(baseUpper, "rgb(50,50,50)", font1, left + 26, top + height / 2 - tSize2.cy - tSize.cy / 2);
                if(cell.text2 && cell.text2.length > 0){
                    paint.drawText(strVolume, "rgb(50,50,50)", font2, left + 39 + t2Size.cx, top + height / 2 + tSize2.cy + 3 - tSize2.cy / 2);
                }else{
                    paint.drawText(strVolume, "rgb(50,50,50)", font2, left + 39, top + height / 2 + tSize2.cy + 3 - tSize2.cy / 2);
                }
            }
            let tSize5 = paint.textSize("100000.00%", font3);
            let rate2 = 1 - 210 / width;
            if (gPaint.isMobile) {
                rate2 = 0.5;
            }
            let colRect = new FCRect(left + width * rate2 + 5, top + height / 2 - tSize5.cy - 4, left + width * rate2 + 5 + tSize5.cx, top + height / 2 + tSize5.cy + 3);
            if (!gPaint.isMobile && width > 500) {
                if (grid.paint.defaultUIStyle == "dark") {
                    paint.drawTextAutoEllipsis(strPrice, "rgb(200,200,200)", font3, left + 200 + 30, top + height / 2 - tSize5.cy / 2, width - 260, left + 230 + 5 + tSize5.cy - tSize5.cy / 2);
                } else {
                    paint.drawTextAutoEllipsis(strPrice, "rgb(50,50,50)", font3, left + 200 + 30, top + height / 2 - tSize5.cy / 2, width - 260, left + 230 + 5 + tSize5.cy - tSize5.cy / 2);
                }
                if (grid.paint.defaultUIStyle == "dark") {
                    paint.drawLine("rgb(0,0,0)", 2, 0, width - 240, top + 5, width - 240, bottom - 5);
                    paint.drawLine("rgb(0,0,0)", 2, 0, left + 210, top + 5, left + 210, bottom - 5);
                } else {
                    paint.drawLine("rgb(200,200,200)", 1, 0, width - 240, top + 5, width - 240, bottom - 5);
                    paint.drawLine("rgb(200,200,200)", 1, 0, left + 210, top + 5, left + 210, bottom - 5);
                }
                //paint.drawLine("rgb(50,50,50)", 1, 0, left + 200 + 5 - 10, top, left + 200 + 5 - 10, bottom);
                //paint.drawLine("rgb(50,50,50)", 1, 0, width - 220, top, width - 220, bottom);
            }
            if (grid.paint.defaultUIStyle == "dark") {
                if(gList.image2){
                    paint.fillRoundRect("rgba(32,36,38,230)", colRect.left, top + 15, colRect.right, bottom - 15, 5);
                }else{
                    if (!gPaint.isMobile && width > 500) {
                        paint.fillRoundRect("rgba(32,36,38,100)", colRect.left, top + 15, colRect.right, bottom - 15, 5);
                    }else{
                        paint.fillRoundRect("rgb(32,36,38)", colRect.left, top + 15, colRect.right, bottom - 15, 5);
                    }
                }
                if(mouseMovePoint.x >= colRect.left && mouseMovePoint.x <= colRect.right && mouseMovePoint.y >= top + 15 && mouseMovePoint.y <= bottom - 15){
                    paint.drawRoundRect("rgb(42,138,195)", 1, 0, colRect.left, top + 15, colRect.right, bottom - 15, 5);
                }
                buttonRects.push(new FCRect(colRect.left, top + 15, colRect.right, bottom - 15, 5));
                //paint.drawRoundRect("rgb(75,75,75)", 1, 0, colRect.left, colRect.top, colRect.right, colRect.bottom, 10);
            } else {
                paint.fillRoundRect("rgb(255,255,255)", colRect.left, top + 15, colRect.right, bottom - 15, 5);
                paint.drawRoundRect("rgb(200,200,200)", 1, 0, colRect.left, top + 15, colRect.right, bottom - 15, 5);
            }

            let diffX = colRect.right - colRect.left + 10;
            if (cell.linkText2.length > 0) {
                if (grid.paint.defaultUIStyle == "dark") {
                    if(gList.image2){
                        paint.fillRoundRect("rgba(32,36,38,230)", colRect.left + diffX, top + 15, colRect.right + diffX, bottom - 15, 5);
                    }else{
                        if (!gPaint.isMobile && width > 500) {
                            paint.fillRoundRect("rgba(32,36,38,100)", colRect.left + diffX, top + 15, colRect.right + diffX, bottom - 15, 5);
                        }else{
                            paint.fillRoundRect("rgb(32,36,38)", colRect.left + diffX, top + 15, colRect.right + diffX, bottom - 15, 5);
                        }
                    }
                    //paint.drawRoundRect("rgb(75,75,75)", 1, 0, colRect.left + diffX, colRect.top, colRect.right + diffX, colRect.bottom, 4);
                } else {
                    paint.fillRoundRect("rgb(255,255,255)", colRect.left + diffX, top + 15, colRect.right + diffX, bottom - 15, 5);
                    paint.drawRoundRect("rgb(200,200,200)", 1, 0, colRect.left + diffX, top + 15, colRect.right + diffX, bottom - 15, 5);
                }
                if(mouseMovePoint.x >= colRect.left + diffX && mouseMovePoint.x <= colRect.right + diffX && mouseMovePoint.y >= top + 15 && mouseMovePoint.y <= bottom - 15){
                    paint.drawRoundRect("rgb(42,138,195)", 1, 0, colRect.left + diffX, top + 15, colRect.right + diffX, bottom - 15, 5);
                }
                buttonRects.push(new FCRect(colRect.left + diffX, top + 15, colRect.right + diffX, bottom - 15));
            }
            cell.diffX = diffX;
            let tSize4 = paint.textSize(cell.linkText1, font3);
            let tSize6 = paint.textSize(cell.linkText2, font3);
            let offsetRight = 15;
            if (cell.image) {
                if (!cell.initImage) {
                    cell.initImage = true;
                    let image = new Image();
                    image.onload = function () {
                        cell.image2 = image;
                        invalidateView(grid);
                    };
                    image.src = cell.image;
                }
            }
            if (grid.paint.defaultUIStyle == "dark") {
                paint.drawText(cell.linkText1, "rgb(200,200,200)", font3, left + width * rate2 + 5 + tSize5.cx / 2 - tSize4.cx / 2 - 15, top + height / 2 - tSize4.cy / 2);
            } else {
                paint.drawText(cell.linkText1, "rgb(50,50,50)", font3, left + width * rate2 + 5 + tSize5.cx / 2 - tSize4.cx / 2 - 15, top + height / 2 - tSize4.cy / 2);
            }
            let tLeft1 = left + width * rate2 + 5 + tSize5.cx / 2 - tSize4.cx / 2 - 15 + tSize4.cx + 10;
            let tLeftRect = new FCRect(tLeft1 + 2, top + height / 2 - 10, tLeft1 + 20 - 2, top + height / 2 + 10);
            if(cell.linkText1 == "视频"){
                tLeftRect.left -= 2;
                tLeftRect.right += 2;
                paint.drawEllipse("rgb(59,174,218)", 1, 0, tLeftRect.left, tLeftRect.top, tLeftRect.right, tLeftRect.bottom);
                let lR = 2;
                paint.fillEllipse("rgb(59,174,218)", tLeftRect.left + (tLeftRect.right - tLeftRect.left) / 2 - lR, 
                tLeftRect.top + (tLeftRect.bottom - tLeftRect.top) / 4 - lR, tLeftRect.left + (tLeftRect.right - tLeftRect.left) / 2 + lR, 
                tLeftRect.top + (tLeftRect.bottom - tLeftRect.top) / 4 + lR);
                paint.fillEllipse("rgb(59,174,218)", tLeftRect.left + (tLeftRect.right - tLeftRect.left) / 2 - lR, 
                tLeftRect.top + (tLeftRect.bottom - tLeftRect.top) * 3 / 4 - lR, tLeftRect.left + (tLeftRect.right - tLeftRect.left) / 2 + lR, 
                tLeftRect.top + (tLeftRect.bottom - tLeftRect.top) * 3 / 4 + lR);
                paint.fillEllipse("rgb(59,174,218)", tLeftRect.left + (tLeftRect.right - tLeftRect.left) / 4 - lR, 
                tLeftRect.top + (tLeftRect.bottom - tLeftRect.top) / 2 - lR, tLeftRect.left + (tLeftRect.right - tLeftRect.left) / 4 + lR, 
                tLeftRect.top + (tLeftRect.bottom - tLeftRect.top) / 2 + lR);
                paint.fillEllipse("rgb(59,174,218)", tLeftRect.left + (tLeftRect.right - tLeftRect.left) * 3 / 4 - lR, 
                tLeftRect.top + (tLeftRect.bottom - tLeftRect.top) / 2 - lR, tLeftRect.left + (tLeftRect.right - tLeftRect.left) * 3 / 4 + lR, 
                tLeftRect.top + (tLeftRect.bottom - tLeftRect.top) / 2 + lR);
            }else if(cell.linkText1 == "示例"){
                let points1 = new Array();
                points1.push(new FCPoint(tLeftRect.left + (tLeftRect.right - tLeftRect.left) / 2 - 5, tLeftRect.top + (tLeftRect.bottom - tLeftRect.top) / 2 - 5));
                points1.push(new FCPoint(tLeftRect.left + (tLeftRect.right - tLeftRect.left) / 2 - 5, tLeftRect.top + (tLeftRect.bottom - tLeftRect.top) / 2 + 5));
                points1.push(new FCPoint(tLeftRect.left + (tLeftRect.right - tLeftRect.left) / 2 + 5, tLeftRect.top + (tLeftRect.bottom - tLeftRect.top) / 2));
                paint.fillPolygon("rgb(170,178,189)", points1);
            }else{
                paint.drawRoundRect("rgb(175,175,175)", 1, 0, tLeftRect.left, tLeftRect.top, tLeftRect.right, tLeftRect.bottom, 2);
                paint.drawLine("rgb(175,175,175)", 1, 0, tLeftRect.left + 4, tLeftRect.top + (tLeftRect.bottom - tLeftRect.top) / 4, tLeftRect.right - 4, tLeftRect.top + (tLeftRect.bottom - tLeftRect.top) / 4);
                paint.drawLine("rgb(175,175,175)", 1, 0, tLeftRect.left + 4, tLeftRect.top + (tLeftRect.bottom - tLeftRect.top) / 2, tLeftRect.left + 7, tLeftRect.top + (tLeftRect.bottom - tLeftRect.top) / 2);
                paint.drawLine("rgb(175,175,175)", 1, 0, tLeftRect.left + 4, tLeftRect.top + (tLeftRect.bottom - tLeftRect.top) * 3 / 4, tLeftRect.left + 7, tLeftRect.top + (tLeftRect.bottom - tLeftRect.top) * 3 / 4);
                paint.drawText("A", "rgb(175,175,175)", "Default,10.5", tLeftRect.left + 8, tLeftRect.top + 8);
            }
            if (cell.linkText2.length > 0) {
                if (cell.image2) {
                    let tLeft = left + width * rate2 + 5 + tSize5.cx / 2 - tSize6.cx / 2 + diffX - offsetRight;
                    if (grid.paint.defaultUIStyle == "dark") {
                        paint.drawText(cell.linkText2, "rgb(200,200,200)", font3, tLeft, top + height / 2 - tSize4.cy / 2);
                    } else {
                        paint.drawText(cell.linkText2, "rgb(50,50,50)", font3, tLeft, top + height / 2 - tSize4.cy / 2);
                    }
                    paint.drawImage(cell.image2, tLeft + tSize6.cx + 10, top + height / 2 - 12, tLeft + tSize6.cx + 34, top + height / 2 + 12);
                } else {
                    let tLeft = left + width * rate2 + 5 + tSize5.cx / 2 - tSize6.cx / 2 + diffX - offsetRight;
                    if (grid.paint.defaultUIStyle == "dark") {
                        paint.drawText(cell.linkText2, "rgb(200,200,200)", font3, tLeft, top + height / 2 - tSize4.cy / 2);
                    } else {
                        paint.drawText(cell.linkText2, "rgb(50,50,50)", font3, tLeft, top + height / 2 - tSize4.cy / 2);
                    }
                    let tLeft1 = tLeft + tSize6.cx + 10;
                    tLeftRect = new FCRect(tLeft1 + 2, top + height / 2 - 10, tLeft1 + 20 - 2, top + height / 2 + 10);
                    if(cell.linkText2 == "图片"){
                        tLeftRect.top += 1;
                        tLeftRect.bottom -= 1;
                        tLeftRect.left -= 1;
                        tLeftRect.right += 1;
                        paint.drawRoundRect("rgb(140,192,81)", 1, 0, tLeftRect.left, tLeftRect.top, tLeftRect.right, tLeftRect.bottom, 2);
                        let points1 = new Array();
                        points1.push(new FCPoint(tLeftRect.left + 1, tLeftRect.bottom));
                        points1.push(new FCPoint(tLeftRect.left + 5, tLeftRect.bottom - 12));
                        points1.push(new FCPoint(tLeftRect.left + 12, tLeftRect.bottom));
                        paint.fillPolygon("rgb(140,192,81)", points1);
                        let points2 = new Array();
                        points2.push(new FCPoint(tLeftRect.left + 7, tLeftRect.bottom));
                        points2.push(new FCPoint(tLeftRect.left + 11, tLeftRect.bottom - 10));
                        points2.push(new FCPoint(tLeftRect.left + 15, tLeftRect.bottom));
                        paint.fillPolygon("rgb(140,192,81)", points2);
                        let lR = 2;
                        paint.fillEllipse("rgb(140,192,81)", tLeftRect.left + (tLeftRect.right - tLeftRect.left) * 3 / 4 - lR, 
                        tLeftRect.top + (tLeftRect.bottom - tLeftRect.top) / 4 - lR, tLeftRect.left + (tLeftRect.right - tLeftRect.left) * 3 / 4 + lR, 
                        tLeftRect.top + (tLeftRect.bottom - tLeftRect.top) / 4 + lR);
                    }else if(cell.linkText2 == "下载"){
                        let points1 = new Array();
                        points1.push(new FCPoint(tLeftRect.left + (tLeftRect.right - tLeftRect.left) / 2 - 3, tLeftRect.top + (tLeftRect.bottom - tLeftRect.top) / 2 - 8));
                        points1.push(new FCPoint(tLeftRect.left + (tLeftRect.right - tLeftRect.left) / 2 + 3, tLeftRect.top + (tLeftRect.bottom - tLeftRect.top) / 2 - 8));
                        points1.push(new FCPoint(tLeftRect.left + (tLeftRect.right - tLeftRect.left) / 2 + 3, tLeftRect.top + (tLeftRect.bottom - tLeftRect.top) / 2));
                        points1.push(new FCPoint(tLeftRect.left + (tLeftRect.right - tLeftRect.left) / 2 + 8, tLeftRect.top + (tLeftRect.bottom - tLeftRect.top) / 2));
                        points1.push(new FCPoint(tLeftRect.left + (tLeftRect.right - tLeftRect.left) / 2, tLeftRect.top + (tLeftRect.bottom - tLeftRect.top) / 2 + 9));
                        points1.push(new FCPoint(tLeftRect.left + (tLeftRect.right - tLeftRect.left) / 2 - 8, tLeftRect.top + (tLeftRect.bottom - tLeftRect.top) / 2));
                        points1.push(new FCPoint(tLeftRect.left + (tLeftRect.right - tLeftRect.left) / 2 - 3, tLeftRect.top + (tLeftRect.bottom - tLeftRect.top) / 2));
                        paint.fillPolygon("rgb(170,178,189)", points1);
                    }else{
                        paint.drawRoundRect("rgb(175,175,175)", 1, 0, tLeftRect.left, tLeftRect.top, tLeftRect.right, tLeftRect.bottom, 2);
                        paint.drawLine("rgb(175,175,175)", 1, 0, tLeftRect.left + 4, tLeftRect.top + (tLeftRect.bottom - tLeftRect.top) / 4, tLeftRect.right - 4, tLeftRect.top + (tLeftRect.bottom - tLeftRect.top) / 4);
                        paint.drawLine("rgb(175,175,175)", 1, 0, tLeftRect.left + 4, tLeftRect.top + (tLeftRect.bottom - tLeftRect.top) / 2, tLeftRect.left + 7, tLeftRect.top + (tLeftRect.bottom - tLeftRect.top) / 2);
                        paint.drawLine("rgb(175,175,175)", 1, 0, tLeftRect.left + 4, tLeftRect.top + (tLeftRect.bottom - tLeftRect.top) * 3 / 4, tLeftRect.left + 7, tLeftRect.top + (tLeftRect.bottom - tLeftRect.top) * 3 / 4);
                        paint.drawText("A", "rgb(175,175,175)", "Default,10.5", tLeftRect.left + 8, tLeftRect.top + 8);
                    }
                }
            }
            if (tick > 0 && clickIndex == row.index) {
                let overTimes = tick;
                if (overTimes > 360) {
                    overTimes -= 360;
                }
                let dRect = new FCRect(left + 14, top + 5, right - 14, bottom - 5);
                let dWidth = Math.min(dRect.right - dRect.left, dRect.bottom - dRect.top);
                let dInterval = 20;
                let dcWidth = grid.size.cx * 1.5;
                let dcWidth2 = 400;
                if (paint.isMobile) {
                    dcWidth = grid.size.cx;
                    dcWidth2 = 200;
                }
                let showRect = new FCRect(-dcWidth2 + dcWidth * (360 - overTimes) / dcWidth2, dRect.top, dcWidth * (360 - overTimes) / dcWidth2, dRect.bottom);
                if (showRect.left < dRect.left) {
                    showRect.left = dRect.left;
                }
                if (showRect.left > dRect.right) {
                    showRect.left = dRect.right;
                }
                if (showRect.right < dRect.left) {
                    showRect.right = dRect.left;
                }
                if (showRect.right > dRect.right) {
                    showRect.right = dRect.right;
                }
                paint.fillRect("rgba(42,138,195,100)", showRect.left, showRect.top, showRect.right, showRect.bottom);
                paint.drawRect("rgb(42,138,195)", 1, 0, dRect.left, dRect.top, dRect.right, dRect.bottom);
                if (overTimes < 90) {
                    let fSize = (90 - overTimes) * (dWidth - dInterval) / 60;
                    let eSize = overTimes * (dWidth - dInterval) / 60;
                    paint.drawLine("rgba(42,138,195,200)", 3, 0, dRect.right - fSize, dRect.top, dRect.right, dRect.top);
                    paint.drawLine("rgba(42,138,195,200)", 3, 0, dRect.right, dRect.top, dRect.right, dRect.top + eSize);
                }
                else if (overTimes < 180) {
                    let fSize = (90 - (overTimes - 90)) * (dWidth - dInterval) / 60;
                    let eSize = (overTimes - 90) * (dWidth - dInterval) / 60;
                    paint.drawLine("rgba(42,138,195,200)", 3, 0, dRect.right, dRect.bottom - fSize, dRect.right, dRect.bottom);
                    paint.drawLine("rgba(42,138,195,200)", 3, 0, dRect.right, dRect.bottom, dRect.right - eSize, dRect.bottom);
                }
                else if (overTimes < 270) {
                    let fSize = (90 - (overTimes - 180)) * (dWidth - dInterval) / 60;
                    let eSize = (overTimes - 180) * (dWidth - dInterval) / 60;
                    paint.drawLine("rgba(42,138,195,200)", 3, 0, dRect.left, dRect.bottom, dRect.left + fSize, dRect.bottom);
                    paint.drawLine("rgba(42,138,195,200)", 3, 0, dRect.left, dRect.bottom, dRect.left, dRect.bottom - eSize);
                }
                else if (overTimes < 360) {
                    let fSize = (90 - (overTimes - 270)) * (dWidth - dInterval) / 60;
                    let eSize = (overTimes - 270) * (dWidth - dInterval) / 60;
                    paint.drawLine("rgba(42,138,195,200)", 3, 0, dRect.left, dRect.top, dRect.left + eSize, dRect.top);
                    paint.drawLine("rgba(42,138,195,200)", 3, 0, dRect.left, dRect.top, dRect.left, dRect.top + fSize);
                }
                let t1 = 6, t2 = 24;
                paint.beginPath();
                paint.addLine(dRect.left + t1, dRect.top + t2, dRect.left + t1, dRect.top + t1);
                paint.addLine(dRect.left + t1, dRect.top + t1, dRect.left + t2, dRect.top + t1);
                paint.drawPath("rgba(42,138,195,200)", 2, 0);
                paint.closePath();
                paint.beginPath();
                paint.addLine(dRect.left + t1, dRect.bottom - t2, dRect.left + t1, dRect.bottom - t1);
                paint.addLine(dRect.left + t1, dRect.bottom - t1, dRect.left + t2, dRect.bottom - t1);
                paint.drawPath("rgba(42,138,195,200)", 2, 0);
                paint.closePath();
                paint.beginPath();
                paint.addLine(dRect.right - t1, dRect.top + t2, dRect.right - t1, dRect.top + t1);
                paint.addLine(dRect.right - t1, dRect.top + t1, dRect.right - t2, dRect.top + t1);
                paint.drawPath("rgba(42,138,195,200)", 2, 0);
                paint.closePath();
                paint.beginPath();
                paint.addLine(dRect.right - t1, dRect.bottom - t2, dRect.right - t1, dRect.bottom - t1);
                paint.addLine(dRect.right - t1, dRect.bottom - t1, dRect.right - t2, dRect.bottom - t1);
                paint.drawPath("rgba(42,138,195,200)", 2, 0);
                paint.closePath();
            }
        }
    };

    /*
    * 绘制列
    * grid:表格
    * column:列
    * paint:绘图对象
    * left:左侧坐标
    * top:上方坐标
    * right:右侧坐标
    * bottom:下方坐标
    */
    gPaint.onPaintGridColumn = function (grid, column, paint, left, top, right, bottom) {
        if (grid.scrollV < 150) {
            let width = right - left, height = bottom - top;
            let font2 = "Default,16";
            let tSize = paint.textSize("@花卷猫", font2);
            if (!column.image2) {
                let image = new Image();
                image.onload = function () {
                    column.image2 = image;
                    invalidateView(grid);
                };
                image.onerror = function () {
                    column.image2 = image;
                    invalidateView(grid);
                };
                image.src = "images/logo.png";
            }
            else {
                let iR = 20;
                let imageRect = new FCRect(20, 30 - iR, 20 + iR * 2, 30 + iR);
                if (paint.defaultUIStyle == "light") {
                    paint.fillEllipse("rgb(240,240,240)", imageRect.left, imageRect.top, imageRect.right, imageRect.bottom);
                } else {
                    paint.fillEllipse("rgb(32,36,38)", imageRect.left, imageRect.top, imageRect.right, imageRect.bottom);
                }

                if (paint.defaultUIStyle == "light") {
                    paint.drawText("@花卷猫", "rgb(0,0,0)", font2, imageRect.right + 10, imageRect.top + (imageRect.bottom - imageRect.top) / 2 - tSize.cy / 2);
                } else {
                    paint.drawText("@花卷猫", "rgb(200,200,200)", font2, imageRect.right + 10, imageRect.top + (imageRect.bottom - imageRect.top) / 2 - tSize.cy / 2);
                }
                imageRect.left += 6;
                imageRect.top += 6;
                imageRect.right -= 6;
                imageRect.bottom -= 6;
                paint.drawImage(column.image2, imageRect.left, imageRect.top, imageRect.right, imageRect.bottom);
            }
            let bR = 10;
            let blackWhiteRect = new FCRect(grid.size.cx - 25 - bR, 25 - bR, grid.size.cx - 25 + bR, 25 + bR);
            if (paint.defaultUIStyle == "light") {
                paint.fillEllipse("rgb(175,175,175)", blackWhiteRect.left, blackWhiteRect.top, blackWhiteRect.right, blackWhiteRect.bottom);
            } else {
                paint.fillEllipse("rgb(70,76,79)", blackWhiteRect.left, blackWhiteRect.top, blackWhiteRect.right, blackWhiteRect.bottom);
            }
            blackWhiteRect.left += bR;
            blackWhiteRect.right += bR;
            paint.fillEllipse(grid.backColor, blackWhiteRect.left, blackWhiteRect.top, blackWhiteRect.right, blackWhiteRect.bottom);
        }
    };

    /*
    * 重绘边线的实现方法
    * view:视图
    * paint:绘图对象
    * clipRect:裁剪区域
    */
    gPaint.onPaint = function (view, paint, clipRect) {
        let width = view.size.cx;
        paint.fillRect(view.backColor, 0, 0, view.size.cx, view.size.cy);
        buttonRects = [];
        drawGrid(view, paint, clipRect);
    };

    /*
    * 重绘边线的实现方法
    * view:视图
    * paint:绘图对象
    * clipRect:裁剪区域
    */
    gPaint.onPaintBorder = function (view, paint, clipRect) {
        drawGridScrollBar(view, paint, clipRect);
        if (clickIndex > 1) {
            let row = gList.rows[clickIndex];
            let cell = row.cells[0];
            let dFont = "Default,14";
            let gSize = paint.textSize(cell.text4, dFont);
            let divTop = 0;
            let bounds = new FCRect(0, clickIndex * gList.rowHeight + gList.headerHeight - gList.scrollV, gList.size.cx, (clickIndex + 1) * gList.rowHeight + gList.headerHeight - gList.scrollV);
            let dR = 300;
            let mobileMode = false;
            if (paint.isMobile || gList.size.cx <= 500){
                dR = 250;
                mobileMode = true;
            }
            if (!mobileMode){
                bounds = new FCRect(0, (clickIndex - 2) * gList.rowHeight + gList.headerHeight - gList.scrollV + 100, gList.size.cx, (clickIndex - 2 + 1) * gList.rowHeight + gList.headerHeight - gList.scrollV + 100);
            }
            if (mobileMode || gSize.cx > gList.size.cx - 40) {
                let lineCount = 1;
                if (gList.size.cx > 40) {
                    lineCount = parseInt(gSize.cx / (gList.size.cx - 40)) + 1;
                }               
                if (bounds.top < gList.size.cy / 2) {
                    bounds.top += gList.rowHeight;
                    bounds.bottom += gList.rowHeight;
                    if (bounds.bottom - bounds.top - 60 < gSize.cy * lineCount) {
                        bounds.bottom = bounds.top + 60 + gSize.cy * lineCount;
                    }
                    divTop = bounds.bottom + 10;
                } else {
                    bounds.top -= gList.rowHeight;
                    bounds.bottom -= gList.rowHeight;
                    if (bounds.bottom - bounds.top - 60 < gSize.cy * lineCount) {
                        bounds.top = bounds.bottom - 60 - gSize.cy * lineCount;
                    }
                    divTop = bounds.top - dR - 10;
                }
                bounds.left += 10;
                bounds.right -= 10;
                let textColor = "rgb(200,200,200)";
                if (paint.defaultUIStyle == "light") {
                    paint.fillRoundRect("rgba(240,240,240,200)", bounds.left, bounds.top, bounds.right, bounds.bottom, 0);
                    paint.drawRoundRect("rgb(175,175,175)", 1, 0, bounds.left, bounds.top, bounds.right, bounds.bottom, 0);
                    textColor = "rgb(50,50,50)";
                } else {
                    paint.fillRoundRect("rgba(15,15,15,200)", bounds.left, bounds.top, bounds.right, bounds.bottom, 0);
                    paint.drawRoundRect("rgb(75,75,75)", 1, 0, bounds.left, bounds.top, bounds.right, bounds.bottom, 0);
                    textColor = "rgb(200,200,200)";
                }
                let drawText = "";
                let dTop = bounds.top + 10;
                let pos = 0;
                let textLength = cell.text4.length;
                while (pos < textLength) {
                    drawText += cell.text4[pos];
                    let dSize = paint.textSize(drawText, dFont);
                    if (dSize.cx > bounds.right - 40 || pos == textLength - 1) {
                        paint.drawText(drawText, textColor, dFont, bounds.left + 10, dTop);
                        drawText = "";
                        dTop += dSize.cy + 5;
                    }
                    pos++;
                }
            }
            let cellTop = clickIndex * gList.rowHeight + gList.headerHeight - gList.scrollV;
            let cellBottom = (clickIndex + 1) * gList.rowHeight + gList.headerHeight - gList.scrollV
            if(bounds.top < cellTop){
                if(bounds.top < gList.size.cy - bounds.bottom - gList.rowHeight){
                    divTop = cellBottom + 10;
                }else{
                    divTop = bounds.top - dR - 10;
                }
            }else{
                if(bounds.top < gList.size.cy - bounds.bottom + gList.rowHeight){
                    divTop = bounds.bottom + 10;
                }else{
                    divTop = bounds.top - dR - 10 - gList.rowHeight;
                }
            }
            if(cell.rate){
                if(replayTick <= 1 && tick <= 360){
                    return;
                }
                let colors = new Array();
                colors.push("rgb(170, 178, 189)");
                colors.push("rgb(150, 123, 220)");
                colors.push("rgb(140, 192, 81)");
                colors.push("rgb(219, 68, 83)");
                colors.push("rgb(216, 112, 173)"); 
                colors.push("rgb(246, 187, 67)");
                colors.push("rgb(59, 174, 218)");
                colors.push("rgb(75, 137, 220)");
                colors.push("rgb(185, 63, 150)");
                colors.push("rgb(233, 87, 62)");
                let divRect = new FCRect(gList.size.cx / 2 - dR / 2, divTop, gList.size.cx / 2 + dR / 2, divTop + dR);
                let alpha = "230";
                if(replayTick == 10 && tick > 360){
                    alpha = 230 - 230 * (tick - 360) / 360;
                }
                let strColor = colors[Number(cell.linkType) - 1].replace("rgb(", "").replace(")", "");
                if(paint.defaultUIStyle == "dark"){
                    paint.fillEllipse("rgba(15,15,15," + alpha.toString() + ")", divRect.left, divRect.top, divRect.right, divRect.bottom);
                    paint.drawEllipse("rgb(75,75,75)", 1, 0, divRect.left, divRect.top, divRect.right, divRect.bottom);
                }else{
                    paint.fillEllipse("rgba(240,240,240," + alpha.toString() + ")", divRect.left, divRect.top, divRect.right, divRect.bottom);
                    paint.drawEllipse("rgb(150,150,150)", 1, 0, divRect.left, divRect.top, divRect.right, divRect.bottom);
                }
                let aR = 50;
                if(paint.defaultUIStyle == "dark"){
                    paint.fillEllipse("rgba(0,0,0,200)", divRect.left + aR, divRect.top + aR, divRect.right - aR, divRect.bottom - aR);
                    paint.drawEllipse("rgb(75,75,75)", 1, 0, divRect.left + aR, divRect.top + aR, divRect.right - aR, divRect.bottom - aR);
                }else{
                    paint.fillEllipse("rgba(255,255,255,200)", divRect.left + aR, divRect.top + aR, divRect.right - aR, divRect.bottom - aR);
                    paint.drawEllipse("rgb(150,150,150)", 1, 0, divRect.left + aR, divRect.top + aR, divRect.right - aR, divRect.bottom - aR);
                }
                let strs = cell.rate.split(",");
                let oX = divRect.left + (divRect.right - divRect.left) / 2;
                let oY = divRect.top + (divRect.bottom - divRect.top) / 2;
                let r = (divRect.right - divRect.left) / 2 - 50;
                let rPoints = new Array();
                let rPoints2 = new Array();
                let rPoints3 = new Array();
                let rPoints4 = new Array();
                let titles = new Array();
                titles.push("性能高");
                titles.push("内存少");
                titles.push("体积小");
                titles.push("上手易");
                titles.push("功能多");
                titles.push("兼容强");
                let tFont = "Default,14";
                if(cell.linkType == "2"){
                    titles = new Array();
                    titles.push("可视设计");
                    titles.push("浏览器");
                    titles.push("多端互动");
                    titles.push("网站收集");
                    titles.push("工具箱");
                    titles.push("代码编辑");
                }else if(cell.linkType == "1"){
                    titles = new Array();
                    if(row.index > 10){
                        titles.push("研发");
                        titles.push("设计");
                        titles.push("运营");
                        titles.push("自媒体");
                        titles.push("销售");
                        titles.push("项目");
                    }else{
                        titles.push("图形");
                        titles.push("存储");
                        titles.push("通讯服务");
                        titles.push("算法");
                        titles.push("自动化");
                        titles.push("人工智能");
                    }
                }else if(cell.linkType == "6"){
                    titles = new Array();
                    titles.push("基础软件");
                    titles.push("自动化");
                    titles.push("工业软件");
                    titles.push("生产力");
                    titles.push("互联网");
                    titles.push("金融量化");
                }
                let totalRate = 0;
                for(let i = 0; i < strs.length; i++){
                    totalRate = totalRate + parseInt(strs[i]);
                }
                for(let i = 0; i < strs.length; i++){
                    let angle = i * 60 - 60;
                    let angle2 = angle;
                    let cR = r * parseInt(strs[i]) / 100;
                    if(replayTick == 10 && tick > 360){
                        let dTick = (720 - tick);
                        cR = dTick * cR / 360;
                        angle2 += dTick;
                    }else if(replayTick == 1){
                        let dTick = 360 - (720 - tick);
                        cR = dTick * cR / 360;
                        angle2 -= dTick;
                    }
                    let cX = oX + (cR * Math.cos(angle2 * 3.14 / 180));
                    let cY = oY + (cR * Math.sin(angle2 * 3.14 / 180));
                    let cX2 = oX + (r * Math.cos(angle * 3.14 / 180));
                    let cY2 = oY + (r * Math.sin(angle * 3.14 / 180));
                    let cX3 = oX + (r / 3 * Math.cos(angle * 3.14 / 180));
                    let cY3 = oY + (r / 3 * Math.sin(angle * 3.14 / 180));
                    let cX4 = oX + (r * 2 / 3 * Math.cos(angle * 3.14 / 180));
                    let cY4 = oY + (r * 2 / 3 * Math.sin(angle * 3.14 / 180));
                    rPoints.push(new FCPoint(cX, cY));
                    rPoints2.push(new FCPoint(cX2, cY2));
                    rPoints3.push(new FCPoint(cX3, cY3));
                    rPoints4.push(new FCPoint(cX4, cY4));
                    let cX5 = oX + ((r + 25) * Math.cos(angle * 3.14 / 180));
                    let cY5 = oY + ((r + 25) * Math.sin(angle * 3.14 / 180));
                    let rtSize = paint.textSize(titles[i], tFont);
                    if(paint.defaultUIStyle == "dark"){
                        paint.drawText(titles[i], "rgb(255,255,255)", tFont, cX5 - rtSize.cx / 2, cY5 - rtSize.cy / 2);
                    }else{
                        paint.drawText(titles[i], "rgb(0,0,0)", tFont, cX5 - rtSize.cx / 2, cY5 - rtSize.cy / 2);
                    }
                    let tPos = 30;
                    let cX6 = oX + (dR / 2 * Math.cos((angle + tPos) * 3.14 / 180));
                    let cY6 = oY + (dR / 2 * Math.sin((angle + tPos) * 3.14 / 180));
                    let dPos = 20;
                    if(replayTick == 10 && tick > 360){
                        let dTick = (720 - tick);
                        dPos = dTick * dPos / 360;
                    }
                    
                    let cX7 = oX + ((dR / 2 - dPos) * Math.cos((angle + tPos) * 3.14 / 180));
                    let cY7 = oY + ((dR / 2 - dPos) * Math.sin((angle + tPos) * 3.14 / 180));
                    if(paint.defaultUIStyle == "dark"){
                        paint.drawLine("rgb(75,75,75)", 2, 0, cX6, cY6, cX7, cY7);
                    }else{
                        paint.drawLine("rgb(150,150,150)", 1, 0, cX6, cY6, cX7, cY7);
                    }
                }
                let dColor = "rgb(30,30,30)";
                if(paint.defaultUIStyle == "light"){
                    dColor = "rgb(220,220,220)";
                }
                paint.drawLine(dColor, 1, 0, rPoints2[0].x, rPoints2[0].y, rPoints2[3].x, rPoints2[3].y);
                paint.drawLine(dColor, 1, 0, rPoints2[1].x, rPoints2[1].y, rPoints2[4].x, rPoints2[4].y);
                paint.drawLine(dColor, 1, 0, rPoints2[2].x, rPoints2[2].y, rPoints2[5].x, rPoints2[5].y);
                paint.drawPolygon(dColor, 1, 0, rPoints3);
                paint.drawPolygon(dColor, 1, 0, rPoints4);
                paint.fillPolygon("rgba(" + strColor + ",80)", rPoints);
                paint.drawPolygon("rgb(" + strColor + ")", 1, 0, rPoints);
            }
        }
    };

    let checkPaint = function () {
        if (clickIndex != -1) {
            if (gPaint.isMobile) {
                tick -= 20;
            } else {
                tick -= 12;
            }
            if (tick <= 0) {
                replayTick--;
                if(replayTick <= 0){
                    tick = 0;
                    clickIndex = -1;
                }else{
                    tick = 720;
                }
            }
            invalidate(gPaint);
        }
    };

    let clickIndex = -1;
    let tick = 0;
    let replayTick = 0;
    setInterval(checkPaint, 30);
    gPaint.onClickGridCell = function (grid, row, column, cell, firstTouch, firstPoint, secondTouch, secondPoint, clicks) {
        let rate = 1 - 210 / grid.size.cx;
        if (gPaint.isMobile) {
            rate = 0.5;
        }
        if (cell.text3 == "关于") {
            window.location.href = cell.link;
        } else {
            if (firstPoint.x >= grid.size.cx * rate + cell.diffX && firstPoint.x <= grid.size.cx * rate + cell.diffX * 2) {
                if (row.index < 2) {

                } else {
                    window.location.href = cell.link2;
                }
            } else if (firstPoint.x >= grid.size.cx * rate && firstPoint.x <= grid.size.cx * rate + cell.diffX) {
                if (row.index < 2) {

                } else {
                    window.location.href = cell.link;
                }
            } else {
                clickIndex = row.index;
                tick = 720;
                if (row.index < 2) {
                    replayTick = 1;
                }else{
                    replayTick = 10;
                }
            }
        }
    };

    gPaint.onClickGridColumn = function (grid, column, firstTouch, firstPoint, secondTouch, secondPoint, clicks) {
        if (firstPoint.x > grid.size.cx - 50 && grid.scrollV < 150) {
            if (grid.paint.defaultUIStyle == "dark") {
                grid.paint.defaultUIStyle = "light";
            } else {
                grid.paint.defaultUIStyle = "dark";
            }
            if (gList.paint.defaultUIStyle == "dark") {
                gList.backColor = "rgb(0,0,0)";
                gList.borderColor = null;
                gList.textColor = "rgb(255,255,255)";
                gList.scrollBarColor = "rgb(100,100,100)";
            } else if (gList.paint.defaultUIStyle == "light") {
                gList.backColor = "rgb(230,230,230)";
                gList.borderColor = null;
                gList.textColor = "rgb(0,0,0)";
                gList.scrollBarColor = "rgb(200,200,200)";
            }
            invalidate(gPaint);
        }
    }

    let createCell = function(){
        let row = new FCGridRow;
        gList.rows.push(row);
        let cell = new FCGridCell();
        row.cells.push(cell);
        return cell;
    }

    createCell();
    createCell();

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "项目简介";
        cell.text2 = "G";
        cell.text3 = "国产基础框架和软件";
        cell.text4 = "国产专业基础框架和软件，自研各种跨平台或跨语言的图形、通讯、服务、存储、计算、代码编辑器、脚本语言、多端互动、人工智能等基础框架，并优先拿自己的框架做自己的行业产品";
        cell.link = "software/desc/project.txt";
        cell.link2 = "test/document.html";
        cell.linkText1 = "描述";
        cell.linkText2 = "文档";
        cell.linkType = "1";
        cell.image = "images/file-pdf-one.png";
        cell.rate = "90,70,90,80,70,70";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "产品效果";
        cell.text2 = "P";
        cell.text3 = "多行业应用";
        cell.text4 = "基础软件、自动化、工业软件、生产力、智能设备、嵌入式、车载、人工智能、物联网、互联网、金融量化的专业系统开发。";
        cell.link = "test/video.html";
        cell.link2 = "test/picture.html";
        cell.linkText1 = "视频";
        cell.linkText2 = "图片";
        cell.linkType = "1";
        cell.rate = "90,70,90,80,70,70";
    }
    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫终端Windows版";
        cell.text2 = "App";
        cell.text3 = "开发工具(公测)";
        cell.text4 = "框架可视化设计、代码编辑器、多端互动、浏览器、网页收集、工具箱等，解压直接使用。";
        cell.link = "https://mp.weixin.qq.com/s?__biz=Mzg5OTIzODg2Mw==&mid=2247485734&idx=1&sn=f06f0603e911bb90a3ade66140db2a29&chksm=c0571786f7209e90b0f037c8c09cf72110c0bd20537065696c013f915467f77aeca1a215999c#rd";
        cell.link2 = "https://www.jjmfc.com/FaceCat.zip";
        cell.linkText1 = "介绍";
        cell.linkText2 = "下载";
        cell.image = "images/windows.png";
        cell.linkType = "2";
        cell.rate = "70,70,80,80,80,70";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫终端MacOS版";
        cell.text2 = "App";
        cell.text3 = "开发工具(公测)";
        cell.text4 = "框架可视化设计、代码编辑器、多端互动、浏览器、网页收集、工具箱等，打开dmg拖拽到应用中，并到系统偏好设置中添加信任。";
        cell.link = "https://mp.weixin.qq.com/s?__biz=Mzg5OTIzODg2Mw==&mid=2247485736&idx=1&sn=5a15db26f189e83a0c5c56177ba9a806&chksm=c0571788f7209e9ef9e61a47f36e49d8b0614ee04eceda09bdacdcf71c99a166a8eaf2b00412#rd";
        cell.link2 = "https://www.jjmfc.com/FaceCat.dmg";
        cell.image = "images/macos.png";
        cell.linkText1 = "介绍";
        cell.linkText2 = "下载";
        cell.linkType = "2";
        cell.rate = "70,70,80,80,80,70";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫终端安卓版";
        cell.text2 = "App";
        cell.text3 = "开发工具(公测)";
        cell.text4 = "框架可视化设计、代码编辑器、多端互动、浏览器、网页收集、工具箱等，直接下载安装，每次提示更新后需要手动安装。";
        cell.link = "https://mp.weixin.qq.com/s?__biz=Mzg5OTIzODg2Mw==&mid=2247485737&idx=1&sn=5e8cf8839e7f812c56981938c8c9b59f&chksm=c0571789f7209e9fa2dc4645702365101e7f4e06edd0c1d1e1d227befeb1c94907a971f70c3d#rd";
        cell.link2 = "https://www.jjmfc.com/FaceCat.apk";
        cell.image = "images/android.png";
        cell.linkText1 = "介绍";
        cell.linkText2 = "下载";
        cell.linkType = "2";
        cell.rate = "10,70,80,80,70,70";
    }


    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫终端iOS版";
        cell.text2 = "App";
        cell.text3 = "开发工具(公测)";
        cell.text4 = "框架可视化设计、代码编辑器、多端互动、浏览器、网页收集、工具箱等，未上线AppStore，由用户自己用XCode安装。";
        cell.link = "software/desc/iosapp.txt";
        cell.link2 = "https://www.jjmfc.com/software/iosapp.zip";
        cell.image = "images/apple.png";
        cell.linkText1 = "介绍";
        cell.linkText2 = "下载";
        cell.linkType = "2";
        cell.rate = "10,70,80,80,70,70";
    }

if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫多端互动Ubuntu版";
        cell.text2 = "App";
        cell.text3 = "开发工具(公测)";
        cell.text4 = "只有跨平台互发消息和文件的功能，包含完整的源代码，用户可以自己编译运行。";
        cell.link = "software/desc/neuronclient.txt";
        cell.link2 = "https://gitee.com/facecat007/template/tree/master/java/neuronclient";
        cell.image = "images/linux.png";
        cell.linkText1 = "介绍";
        cell.linkText2 = "下载";
        cell.linkType = "2";
        cell.rate = "1,1,30,1,1,1";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫Win32 C/C++框架";
        cell.text2 = "Pro";
        cell.text3 = "客户端+服务端框架";
        cell.text4 = "用于制作要求较高的Windows客户端和服务，全部使用C/C++构建，整个界面仅使用单个窗体进行重绘，只有一个句柄，所有内部组件都是虚拟出来的，鼠标、输入和滚动加速均为模拟。绘图代码与框架完全隔离，可以轻易更换，已分别对接GDI和GDI+，使用Html和可视化工具来配置界面，搭配C++直接获取和操作元素。通讯服务方面完全使用底层接口封装，包含长短连接，支持完成端口。";
        cell.link = "software/codemirror5/mode/facecat/cpp.html";
        cell.link2 = "https://www.jjmfc.com/software/facecat_cpp.zip";
        cell.linkText1 = "示例";
        cell.linkText2 = "下载";
        cell.image = "images/cpp2.png";
        cell.rate = "80,100,100,60,95,100";
        cell.linkType = "7";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫Java-Android框架";
        cell.text2 = "Pro";
        cell.text3 = "App框架";
        cell.text4 = "用于制作要求较高的安卓App，全部使用Java构建，整个界面仅使用单个View进行重绘，所有内部组件都是虚拟出来的，触摸、输入和滚动加速均为模拟。绘图代码与框架完全隔离，可以轻易更换，已对接Canvas绘图，使用Html和可视化工具来配置界面，搭配Java直接获取和操作元素。通讯服务方面使用原始接口封装，包含长短连接，支持NIO。";
        cell.link = "software/codemirror5/mode/facecat/java.html";
        cell.link2 = "https://www.jjmfc.com/software/facecat_android.zip";
        cell.linkText1 = "示例";
        cell.linkText2 = "下载";
        cell.image = "images/android.png";
        cell.rate = "90,80,80,80,95,90";
        cell.linkType = "7";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫Java-Swing框架";
        cell.text2 = "Pro";
        cell.text3 = "客户端+服务端框架";
        cell.text4 = "用于制作要求较高的Windows/Linux客户端和服务，全部使用Java构建，整个界面仅使用单个JPanel进行重绘，所有内部组件都是虚拟出来的，鼠标、输入和滚动加速均为模拟。绘图代码与框架完全隔离，可以轻易更换，已对接Canvas绘图，使用Html和可视化工具来配置界面，搭配Java直接获取和操作元素。通讯服务方面使用原始接口封装，包含长短连接，支持NIO。";
        cell.link = "software/codemirror5/mode/facecat/java.html";
        cell.link2 = "https://www.jjmfc.com/software/facecat_swing.zip";
        cell.linkText1 = "示例";
        cell.linkText2 = "下载";
        cell.image = "images/java.png";
        cell.rate = "70,70,90,70,95,95";
        cell.linkType = "7";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫MacOS C++框架";
        cell.text2 = "Pro";
        cell.text3 = "客户端+服务端框架";
        cell.text4 = "用于制作要求较高的MacOS客户端，全部使用C/C++构建，整个界面仅使用单个NSView进行重绘，所有内部组件都是虚拟出来的，鼠标、输入和滚动加速均为模拟。绘图代码与框架完全隔离，可以轻易更换，已对接Quartz2D，使用Html和可视化工具来配置界面，搭配C++直接获取和操作元素。通讯服务方面完全使用底层接口封装，包含长短连接。";
        cell.link = "software/codemirror5/mode/facecat/cpp.html";
        cell.link2 = "https://www.jjmfc.com/software/facecat_macos.zip";
        cell.linkText1 = "示例";
        cell.linkText2 = "下载";
        cell.image = "images/macos.png";
        cell.rate = "100,90,95,60,95,95";
        cell.linkType = "7";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫iOS C++框架";
        cell.text2 = "Pro";
        cell.text3 = "App框架";
        cell.text4 = "用于制作要求较高的iOS-App，全部使用C/C++构建，整个界面仅使用单个UIView进行重绘，所有内部组件都是虚拟出来的，触摸、输入和滚动加速均为模拟。绘图代码与框架完全隔离，可以轻易更换，已对接Quartz2D，使用Html和可视化工具来配置界面，搭配C++直接获取和操作元素。通讯服务方面完全使用底层接口封装，包含长短连接。";
        cell.link = "software/codemirror5/mode/facecat/cpp.html";
        cell.link2 = "https://www.jjmfc.com/software/facecat_ios.zip";
        cell.linkText1 = "示例";
        cell.linkText2 = "下载";
        cell.image = "images/ios.png";
        cell.rate = "100,90,95,60,95,95";
        cell.linkType = "7";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫C#框架";
        cell.text2 = "Pro";
        cell.text3 = "客户端+服务端框架";
        cell.text4 = "用于制作要求较高的Windows客户端，全部使用C#构建，整个界面仅使用单个Control进行重绘，只有一个句柄，所有内部组件都是虚拟出来的，鼠标、输入和滚动加速均为模拟。绘图代码与框架完全隔离，可以轻易更换，已分别对接GDI和GDI+，使用Html和可视化工具来配置界面，搭配C#直接获取和操作元素。通讯服务方面使用原始接口封装，包含长短连接，支持完成端口。";
        cell.link = "software/codemirror5/mode/facecat/cs.html";
        cell.link2 = "https://www.jjmfc.com/software/facecat_cs.zip";
        cell.linkText1 = "示例";
        cell.linkText2 = "下载";
        cell.image = "images/cs2.png";
        cell.rate = "80,90,90,80,95,90";
        cell.linkType = "7";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫HarmonyOS框架";
        cell.text2 = "Pro";
        cell.text3 = "App框架";
        cell.text4 = "用于制作要求较高的鸿蒙原生应用，全部使用Java构建，整个界面仅使用单个Component进行重绘，所有内部组件都是虚拟出来的，触摸、输入和滚动加速均为模拟。绘图代码与框架完全隔离，可以轻易更换，已对接Canvas绘图，使用Html和可视化工具来配置界面，搭配Java直接获取和操作元素。通讯服务方面使用原始接口封装，包含长短连接，支持NIO。";
        cell.link = "software/codemirror5/mode/facecat/java.html";
        cell.link2 = "https://www.jjmfc.com/software/facecat_ohos.zip";
        cell.linkText1 = "示例";
        cell.linkText2 = "下载";
        cell.image = "images/hos.png";
        cell.rate = "80,80,80,80,95,80";
        cell.linkType = "7";
    }

    
if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫Kotlin框架";
        cell.text2 = "Pro";
        cell.text3 = "App框架";
        cell.text4 = "用于制作要求较高的安卓App，使用Kotlin构建，整个界面仅使用单个View进行重绘，所有内部组件都是虚拟出来的，触摸、输入和滚动加速均为模拟。绘图代码与框架完全隔离，可以轻易更换，已对接Canvas绘图，使用Html和可视化工具来配置界面，搭配Kotlin直接获取和操作元素。通讯服务方面使用原始接口封装，包含长短连接，支持NIO。";
        cell.link = "software/codemirror5/mode/facecat/xml.html";
        cell.link2 = "https://www.jjmfc.com/software/facecat_kotlin.zip";
        cell.linkText1 = "介绍";
        cell.linkText2 = "下载";
        cell.image = "images/kotlin.png";
        cell.rate = "80,80,80,70,95,70";
        cell.linkType = "7";
    }
    
    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫Ubuntu C/C++框架";
        cell.text2 = "Pro";
        cell.text3 = "客户端+服务端框架(内测)";
        cell.text4 = "用于制作要求较高的Ubuntu客户端和服务，全部使用C/C++构建，整个界面仅使用单个窗体进行重绘，所有内部组件都是虚拟出来的，鼠标、输入和滚动加速均为模拟。绘图代码与框架完全隔离，可以轻易更换，已对接SDL2，使用Html和可视化工具来配置界面，搭配C++直接获取和操作元素。通讯服务方面完全使用底层接口封装，包含长短连接，支持NIO。";
        cell.link = "software/codemirror5/mode/facecat/cpp.html";
        cell.link2 = "document/frame/pic1.jpg";
        cell.linkText1 = "示例";
        cell.linkText2 = "图片";
        cell.image = "images/ubuntu.png";
        cell.rate = "80,100,100,60,95,90";
        cell.linkType = "7";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫Android C/C++框架";
        cell.text2 = "Pro";
        cell.text3 = "App框架(内测)";
        cell.text4 = "用于制作要求较高的Android客户端和服务，整个界面仅使用单个View进行重绘，所有内部组件都是虚拟出来的，触摸、输入和滚动加速均为模拟。绘图代码与框架完全隔离，可以轻易更换，已对接Canvas重绘，使用Html和可视化工具来配置界面，搭配C++直接获取和操作元素。通讯服务方面完全使用底层接口封装，包含长短连接。";
        cell.link = "software/codemirror5/mode/facecat/cpp.html";
        cell.link2 = "document/frame/pic2.jpg";
        cell.linkText1 = "示例";
        cell.linkText2 = "图片";
        cell.image = "images/android.png";
        cell.rate = "80,80,80,60,95,70";
        cell.linkType = "7";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫鸿蒙C/C++框架";
        cell.text2 = "Pro";
        cell.text3 = "App框架(内测)";
        cell.text4 = "用于制作要求较高的HarmonyOS客户端和服务，整个界面仅使用单个Component进行重绘，所有内部组件都是虚拟出来的，触摸、输入和滚动加速均为模拟。绘图代码与框架完全隔离，可以轻易更换，已对接Canvas重绘，使用Html和可视化工具来配置界面，搭配C++直接获取和操作元素。通讯服务方面完全使用底层接口封装，包含长短连接。";
        cell.link = "software/codemirror5/mode/facecat/cpp.html";
        cell.link2 = "document/frame/pic3.jpg";
        cell.linkText1 = "示例";
        cell.linkText2 = "图片";
        cell.image = "images/hos.png";
        cell.rate = "80,80,80,60,95,70";
        cell.linkType = "7";
    }
    
    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫多端互动服务端";
        cell.text2 = "Pro";
        cell.text3 = "后端服务框架";
        cell.text4 = "用于私有部署多端互动服务，使用该服务可以让不同的设备间收发消息和互动联合，使用Java构建。";
        cell.link = "software/desc/neuron.txt";
        cell.link2 = "https://gitee.com/facecat007/template/tree/master/java/neuron";
        cell.linkText1 = "介绍";
        cell.linkText2 = "下载";
        cell.image = "images/java.png";
        cell.rate = "80,80,80,80,70,80";
        cell.linkType = "7";
    }
    
    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫Win32 C/C++框架";
        cell.text2 = "Light";
        cell.text3 = "客户端框架";
        cell.text4 = "用于制作Windows客户端，全部使用C/C++构建，整个界面仅使用单个窗体进行重绘，只有一个句柄，所有内部组件都是虚拟出来的，鼠标、输入和滚动加速均为模拟。绘图代码与框架完全隔离，可以轻易更换，已对接GDI+，使用Html和可视化工具来配置界面，搭配C++直接获取和操作元素。";
        cell.link = "software/codemirror5/mode/facecat/cpp.html";
        cell.link2 = "https://gitee.com/facecat007/frame/tree/master/facecat_cpp2";
        cell.linkText1 = "示例";
        cell.linkText2 = "开源";
        cell.image = "images/cpp2.png";
        cell.rate = "80,100,100,60,80,100";
        cell.linkType = "3";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫C#框架";
        cell.text2 = "Light";
        cell.text3 = "客户端框架";
        cell.text4 = "用于制作Windows客户端，全部使用C#构建，整个界面仅使用单个Control进行重绘，只有一个句柄，所有内部组件都是虚拟出来的，鼠标、输入和滚动加速均为模拟。绘图代码与框架完全隔离，可以轻易更换，已对接GDI+，使用Html和可视化工具来配置界面，搭配C#直接获取和操作元素。";
        cell.link = "software/codemirror5/mode/facecat/cs.html";
        cell.link2 = "https://gitee.com/facecat007/frame/tree/master/facecat_cs2";
        cell.linkText1 = "示例";
        cell.linkText2 = "开源";
        cell.image = "images/cs2.png";
        cell.rate = "80,90,90,80,80,90";
        cell.linkType = "3";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫JavaScript框架";
        cell.text2 = "Light";
        cell.text3 = "前端框架";
        cell.text4 = "用于制作Html5的前端，使用JavaScript构建，整个界面仅使用单个Canvas进行重绘，所有内部组件都是虚拟出来的，鼠标、触摸和滚动加速均为模拟，输入框为原生悬浮。绘图代码与框架完全隔离，可以轻易更换，已对接Html5绘图，使用Html和可视化工具来配置界面，搭配JavaScript直接获取和操作元素。";
        cell.link = "software/codemirror5/mode/facecat/javascript.html";
        cell.link2 = "https://gitee.com/facecat007/frame/tree/master/facecat_js";
        cell.linkText1 = "示例";
        cell.linkText2 = "开源";
        cell.image = "images/javascript.png";
        cell.rate = "80,70,95,95,80,90";
        cell.linkType = "3";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫Python框架";
        cell.text2 = "Light";
        cell.text3 = "客户端框架";
        cell.text4 = "用于制作Windows和MacOS客户端，使用Python构建，整个界面仅使用单个窗体进行重绘，使用pywin32或pyobjec，所有内部组件都是虚拟出来的，鼠标、输入和滚动加速均为模拟。绘图代码与框架完全隔离，可以轻易更换，已分别对接GDI、GDI+、Skia和Quartz2D，使用Html和可视化工具来配置界面，搭配Python直接获取和操作元素。";
        cell.link = "software/codemirror5/mode/facecat/python.html";
        cell.link2 = "https://gitee.com/facecat007/frame/tree/master/facecat_py";
        cell.linkText1 = "示例";
        cell.linkText2 = "开源";
        cell.image = "images/python.png";
        cell.rate = "80,90,90,95,80,90";
        cell.linkType = "3";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫Rust框架";
        cell.text2 = "Light";
        cell.text3 = "前端框架";
        cell.text4 = "用于制作Html5的前端，使用Wasm技术，整个界面仅使用单个Canvas进行重绘，所有内部组件都是虚拟出来的，鼠标、触摸和滚动均为模拟，输入框为原生悬浮。绘图代码与框架完全隔离，可以轻易更换，已对接Html5绘图，使用Html和可视化工具来配置界面，搭配Rust直接获取和操作元素。";
        cell.link = "software/codemirror5/mode/facecat/rust.html";
        cell.link2 = "https://gitee.com/facecat007/frame/tree/master/facecat_rust";
        cell.linkText1 = "示例";
        cell.linkText2 = "开源";
        cell.image = "images/rust.png";
        cell.rate = "80,80,80,50,50,70";
        cell.linkType = "3";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫Flutter框架";
        cell.text2 = "Light";
        cell.text3 = "App框架";
        cell.text4 = "用于制作跨平台的前端，使用Dart构建，整个界面仅使用单个CustomPaint进行重绘，所有内部组件都是虚拟出来的，鼠标、触摸和滚动加速均为模拟，输入框为原生悬浮。绘图代码与框架完全隔离，可以轻易更换，使用Html和可视化工具来配置界面，搭配Dart直接获取和操作元素。";
        cell.link = "software/codemirror5/mode/facecat/flutter.html";
        cell.link2 = "https://gitee.com/facecat007/frame/tree/master/facecat_flutter";
        cell.linkText1 = "示例";
        cell.linkText2 = "开源";
        cell.image = "images/flutter.png";
        cell.rate = "70,70,70,60,80,60";
        cell.linkType = "3";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫SwiftUI框架";
        cell.text2 = "Light";
        cell.text3 = "客户端+App框架";
        cell.text4 = "用于制作MacOS和iOS的原生客户端，使用Swift构建，整个界面仅使用单个UIView或NSView进行重绘，所有内部组件都是虚拟出来的，触摸和滚动加速均为模拟，输入框为原生悬浮。绘图代码与框架完全隔离，可以轻易更换，已对接Quartz2D，使用Html和可视化工具来配置界面，搭配Swift直接获取和操作元素。";
        cell.link = "software/codemirror5/mode/facecat/swift.html";
        cell.link2 = "https://gitee.com/facecat007/frame/tree/master/facecat_swiftui";
        cell.linkText1 = "示例";
        cell.linkText2 = "开源";
        cell.image = "images/swiftui.png";
        cell.rate = "95,80,80,60,80,80";
        cell.linkType = "3";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫Go框架";
        cell.text2 = "Light";
        cell.text3 = "客户端框架";
        cell.text4 = "用于制作Windows客户端，以及wasm的前端，使用Go构建，整个界面仅使用单个窗体或Canvas进行重绘，所有内部组件都是虚拟出来的，鼠标、输入和滚动均为模拟。绘图代码与框架完全隔离，可以轻易更换，已对接GDI+、Skia和Html5，使用Html和可视化工具来配置界面，搭配Go直接获取和操作元素。";
        cell.link = "software/codemirror5/mode/facecat/go.html";
        cell.link2 = "https://gitee.com/facecat007/frame/tree/master/facecat_go";
        cell.linkText1 = "示例";
        cell.linkText2 = "开源";
        cell.image = "images/go.png";
        cell.rate = "80,90,90,70,70,70";
        cell.linkType = "3";
    }
    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫TypeScript框架";
        cell.text2 = "Light";
        cell.text3 = "前端框架";
        cell.text4 = "用于制作前端应用，使用TypeScript构建，整个界面仅使用单个Canvas进行重绘，所有内部组件都是虚拟出来的，鼠标、触摸和滚动加速均为模拟，输入框为原生悬浮。绘图代码与框架完全隔离，可以轻易更换，已对接Html5绘图，使用Html和可视化工具来配置界面，搭配TypeScript直接获取和操作元素。";
        cell.link = "software/codemirror5/mode/facecat/typescript.html";
        cell.link2 = "https://gitee.com/facecat007/frame/tree/master/facecat_ts";
        cell.linkText1 = "示例";
        cell.linkText2 = "开源";
        cell.image = "images/ts.png";
        cell.rate = "80,70,80,70,80,70";
        cell.linkType = "3";
    }
    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫Vue框架";
        cell.text2 = "Light";
        cell.text3 = "前端框架";
        cell.text4 = "用于制作前端应用，使用JavaScript构建，整个界面仅使用单个Canvas进行重绘，所有内部组件都是虚拟出来的，鼠标、触摸和滚动加速均为模拟，输入框为原生悬浮。绘图代码与框架完全隔离，可以轻易更换，已对接Html5绘图，使用Html和可视化工具来配置界面，搭配JavaScript直接获取和操作元素。";
        cell.link = "software/codemirror5/mode/facecat/vue.html";
        cell.link2 = "https://gitee.com/facecat007/frame/tree/master/facecat_vue";
        cell.linkText1 = "示例";
        cell.linkText2 = "开源";
        cell.image = "images/vue.png";
        cell.rate = "80,70,80,90,80,80";
        cell.linkType = "3";
    }
    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫ReactNative框架";
        cell.text2 = "Light";
        cell.text3 = "App框架";
        cell.text4 = "用于制作前端应用，使用JavaScript构建，整个界面仅使用单个Canvas进行重绘，所有内部组件都是虚拟出来的，触摸和滚动加速均为模拟，输入框为原生悬浮。绘图代码与框架完全隔离，可以轻易更换，使用Html和可视化工具来配置界面，搭配JavaScript直接获取和操作元素。";
        cell.link = "software/codemirror5/mode/facecat/reactnative.html";
        cell.link2 = "https://gitee.com/facecat007/frame/tree/master/facecat_reactnative";
        cell.linkText1 = "示例";
        cell.linkText2 = "开源";
        cell.image = "images/react.png";
        cell.rate = "80,70,80,50,80,80";
        cell.linkType = "3";
    }
    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫UniApp框架";
        cell.text2 = "Light";
        cell.text3 = "前端框架";
        cell.text4 = "用于制作UniApp的前端应用，使用JavaScript构建， 整个界面仅使用单个Canvas进行重绘，所有内部组件都是虚拟出来的，鼠标、触摸和滚动加速均为模拟，输入框为原生悬浮。绘图代码与框架完全隔离，可以轻易更换，已对接Html5绘图，使用Html和可视化工具来配置界面，搭配JavaScript直接获取和操作元素。";
        cell.link = "software/codemirror5/mode/facecat/uniapp.html";
        cell.link2 = "https://gitee.com/facecat007/frame/tree/master/facecat_uniapp";
        cell.linkText1 = "示例";
        cell.linkText2 = "开源";
        cell.image = "images/uniapp.png";
        cell.rate = "60,70,80,70,80,80";
        cell.linkType = "3";
    }
    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫小程序框架";
        cell.text2 = "Light";
        cell.text3 = "前端框架";
        cell.text4 = "用于制作小程序的前端应用，使用JavaScript构建，整个界面仅使用单个Canvas进行重绘，所有内部组件都是虚拟出来的，触摸和滚动加速均为模拟，输入框为原生悬浮。绘图代码与框架完全隔离，可以轻易更换，已对接Html5绘图，使用Html和可视化工具来配置界面，搭配JavaScript直接获取和操作元素。";
        cell.link = "software/codemirror5/mode/facecat/wechat.html";
        cell.link2 = "https://gitee.com/facecat007/frame/tree/master/facecat_wechat";
        cell.linkText1 = "示例";
        cell.linkText2 = "开源";
        cell.image = "images/mini.png";
        cell.rate = "80,70,80,70,80,80";
        cell.linkType = "3";
    }
    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫R框架";
        cell.text2 = "Light";
        cell.text3 = "客户端框架";
        cell.text4 = "用于制作Windows客户端，使用JavaScript来构建界面，可调用R代码";
        cell.link = "software/codemirror5/mode/facecat/javascript.html";
        cell.link2 = "https://gitee.com/facecat007/frame/tree/master/facecat_r";
        cell.linkText1 = "介绍";
        cell.linkText2 = "开源";
        cell.image = "images/r.png";
        cell.rate = "80,60,60,50,80,80";
        cell.linkType = "3";
    }
    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫Ruby框架";
        cell.text2 = "Light";
        cell.text3 = "客户端框架";
        cell.text4 = "用于制作Windows客户端，使用Ruby构建，整个界面仅使用单个窗体进行重绘，直接对接Windows消息，只有一个句柄，所有内部组件都是虚拟出来的，鼠标、输入和滚动均为模拟。绘图代码与框架完全隔离，可以轻易更换，已对接GDI+，使用Html和可视化工具来配置界面，搭配Ruby直接获取和操作元素。";
        cell.link = "software/codemirror5/mode/facecat/ruby.html";
        cell.link2 = "https://gitee.com/facecat007/frame/tree/master/facecat_ruby";
        cell.linkText1 = "示例";
        cell.linkText2 = "开源";
        cell.image = "images/ruby.png";
        cell.rate = "70,90,90,60,80,80";
        cell.linkType = "3";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫PHP框架";
        cell.text2 = "Light";
        cell.text3 = "前端框架";
        cell.text4 = "用于制作PHP的前端，使用JavaScript构建，整个界面仅使用单个Canvas进行重绘，所有内部组件都是虚拟出来的，鼠标、触摸和滚动加速均为模拟，输入框为原生悬浮。绘图代码与框架完全隔离，可以轻易更换，已对接Html5绘图，使用Html和可视化工具来配置界面，搭配JavaScript直接获取和操作元素。";
        cell.link = "software/codemirror5/mode/facecat/javascript.html";
        cell.link2 = "https://gitee.com/facecat007/frame/tree/master/facecat_php";
        cell.linkText1 = "示例";
        cell.linkText2 = "开源";
        cell.image = "images/php.png";
        cell.rate = "80,70,90,95,80,80";
        cell.linkType = "3";
    }
    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫Electron框架";
        cell.text2 = "Light";
        cell.text3 = "客户端框架";
        cell.text4 = "用于制作客户端，使用Electron构建，整个界面仅使用单个Canvas进行重绘，所有内部组件都是虚拟出来的，鼠标、触摸和滚动加速均为模拟，输入框为原生悬浮。绘图代码与框架完全隔离，可以轻易更换，已对接Html5绘图，使用Html和可视化工具来配置界面，搭配JavaScript直接获取和操作元素。";
        cell.link = "software/codemirror5/mode/facecat/electron.html";
        cell.link2 = "https://gitee.com/facecat007/frame/tree/master/facecat_electron";
        cell.linkText1 = "示例";
        cell.linkText2 = "开源";
        cell.image = "images/electron.png";
        cell.rate = "80,70,50,80,80,80";
        cell.linkType = "3";
    }
    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫Tauri框架";
        cell.text2 = "Light";
        cell.text3 = "客户端框架";
        cell.text4 = "用于制作客户端，使用Tauri构建，整个界面仅使用单个Canvas进行重绘，所有内部组件都是虚拟出来的，鼠标、触摸和滚动加速均为模拟，输入框为原生悬浮。绘图代码与框架完全隔离，可以轻易更换，已对接Html5绘图，使用Html和可视化工具来配置界面，搭配JavaScript直接获取和操作元素。";
        cell.link = "software/codemirror5/mode/facecat/tauri.html";
        cell.link2 = "https://gitee.com/facecat007/frame/tree/master/facecat_tauri";
        cell.linkText1 = "示例";
        cell.linkText2 = "开源";
        cell.image = "images/tauri.png";
        cell.rate = "80,70,80,80,80,80";
        cell.linkType = "3";
    }
    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫Next.js框架";
        cell.text2 = "Light";
        cell.text3 = "前端框架";
        cell.text4 = "用于制作Next.js的前端，使用JavaScript和React构建，整个界面仅使用单个Canvas进行重绘，所有内部组件都是虚拟出来的，鼠标、触摸和滚动加速均为模拟，输入框为原生悬浮。绘图代码与框架完全隔离，可以轻易更换，已对接Html5绘图，使用Html和可视化工具来配置界面，搭配JavaScript直接获取和操作元素。";
        cell.link = "software/codemirror5/mode/facecat/nextjs.html";
        cell.link2 = "https://gitee.com/facecat007/frame/tree/master/facecat_nextjs";
        cell.linkText1 = "示例";
        cell.linkText2 = "开源";
        cell.image = "images/nextjs.png";
        cell.rate = "80,70,80,80,80,80";
        cell.linkType = "3";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫鸿蒙Arkts框架";
        cell.text2 = "Light";
        cell.text3 = "App框架";
        cell.text4 = "用于制作HarmonyOS的前端应用，使用Arkts，整个界面仅使用单个Canvas进行重绘，所有内部组件都是虚拟出来的，触摸和滚动加速均为模拟，输入框为原生悬浮。绘图代码与框架完全隔离，可以轻易更换，已对接Canvas绘图，使用Html和可视化工具来配置界面，搭配TypeScript直接获取和操作元素。";
        cell.link = "software/codemirror5/mode/facecat/arkts.html";
        cell.link2 = "https://gitee.com/facecat007/frame/tree/master/facecat_arkts";
        cell.linkText1 = "示例";
        cell.linkText2 = "开源";
        cell.image = "images/arkts.png";
        cell.rate = "80,70,80,60,70,70";
        cell.linkType = "3";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫UniAppX框架";
        cell.text2 = "Light";
        cell.text3 = "App框架";
        cell.text4 = "用于制作UniAppX的前端应用，使用TypeScript，整个界面仅使用单个Canvas进行重绘，所有内部组件都是虚拟出来的，鼠标、触摸和滚动加速均为模拟。绘图代码与框架完全隔离，可以轻易更换，已对接Canvas绘图，使用Html和可视化工具来配置界面，搭配TypeScript直接获取和操作元素。";
        cell.link = "software/codemirror5/mode/facecat/uniappx.html";
        cell.link2 = "https://gitee.com/facecat007/frame/tree/master/facecat_uniappx";
        cell.linkText1 = "示例";
        cell.linkText2 = "开源";
        cell.image = "images/uniapp.png";
        cell.rate = "80,70,80,40,60,50";
        cell.linkType = "3";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫Qt框架";
        cell.text2 = "Light";
        cell.text3 = "客户端框架";
        cell.text4 = "用于制作客户端，使用C++构建，整个界面仅使用单个Widget进行重绘，所有内部组件都是虚拟出来的，鼠标和滚动加速均为模拟。绘图代码与框架完全隔离，可以轻易更换，已对接QPainter和QGraphicsView，使用Html和可视化工具来配置界面，搭配C++直接获取和操作元素。";
        cell.link = "document/frame/pic6.jpg";
        cell.link2 = "https://gitee.com/facecat007/frame/tree/master/facecat_qt/cpp";
        cell.linkText1 = "图片";
        cell.linkText2 = "开源";
        cell.image = "images/qt.png";
        cell.rate = "90,90,70,60,95,90";
        cell.linkType = "3";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫PyQt框架";
        cell.text2 = "Light";
        cell.text3 = "客户端框架";
        cell.text4 = "用于制作客户端，使用PyQt构建，整个界面仅使用单个Widget进行重绘，所有内部组件都是虚拟出来的，鼠标、输入和滚动加速均为模拟。绘图代码与框架完全隔离，可以轻易更换，已对接QPainter，使用Html和可视化工具来配置界面，搭配Python直接获取和操作元素。";
        cell.link = "document/frame/pic5.jpg";
        cell.link2 = "https://gitee.com/facecat007/frame/tree/master/facecat_qt/pyqt";
        cell.linkText1 = "图片";
        cell.linkText2 = "开源";
        cell.image = "images/qt.png";
        cell.rate = "85,80,70,90,95,90";
        cell.linkType = "3";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫PySide框架";
        cell.text2 = "Light";
        cell.text3 = "客户端框架";
        cell.text4 = "用于制作客户端，使用PySide构建，整个界面仅使用单个QMainWindow进行重绘，所有内部组件都是虚拟出来的，鼠标、输入和滚动加速均为模拟。绘图代码与框架完全隔离，可以轻易更换，已对接QPainter，使用Html和可视化工具来配置界面，搭配Python直接获取和操作元素。";
        cell.link = "document/frame/pyside.jpg";
        cell.link2 = "https://gitee.com/facecat007/frame/tree/master/facecat_qt/pyside";
        cell.linkText1 = "图片";
        cell.linkText2 = "开源";
        cell.image = "images/qt.png";
        cell.rate = "80,80,70,90,95,90";
        cell.linkType = "3";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫Maui框架";
        cell.text2 = "Light";
        cell.text3 = "客户端+App框架";
        cell.text4 = "用于制作.Net的跨平台客户端，全部使用C#构建，整个界面仅使用单个GraphicsView进行重绘，只有一个句柄，所有内部组件都是虚拟出来的，鼠标、触摸和滚动加速均为模拟。绘图代码与框架完全隔离，可以轻易更换，已对接Canvas，使用Html和可视化工具来配置界面，搭配Python直接获取和操作元素。";
        cell.link = "software/codemirror5/mode/facecat/cs.html";
        cell.link2 = "https://gitee.com/facecat007/frame/tree/master/facecat_maui";
        cell.linkText1 = "示例";
        cell.linkText2 = "开源";
        cell.image = "images/maui.png";
        cell.rate = "80,70,60,70,50,70";
        cell.linkType = "3";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫WPF框架";
        cell.text2 = "Light";
        cell.text3 = "客户端框架";
        cell.text4 = "用于制作WPF客户端，全部使用C#构建，整个界面仅使用单个Control进行重绘，只有一个句柄，所有内部组件都是虚拟出来的，鼠标、输入和滚动加速均为模拟。绘图代码与框架完全隔离，可以轻易更换，已分别对接GDI+和WPF，使用Html和可视化工具来配置界面，搭配C#直接获取和操作元素。";
        cell.link = "software/codemirror5/mode/facecat/cs.html";
        cell.link2 = "https://gitee.com/facecat007/frame/tree/master/facecat_wpf";
        cell.linkText1 = "示例";
        cell.linkText2 = "开源";
        cell.image = "images/wpf.png";
        cell.rate = "80,70,80,70,80,80";
        cell.linkType = "3";
    }
    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫Avalonia框架";
        cell.text2 = "Light";
        cell.text3 = "客户端+App框架";
        cell.text4 = "用于制作Avalonia客户端，全部使用C#构建，整个界面仅使用单个UserControl进行重绘，只有一个句柄，所有内部组件都是虚拟出来的，鼠标和滚动加速均为模拟。绘图代码与框架完全隔离，可以轻易更换，已对接DrawingContext，使用Html和可视化工具来配置界面，搭配C#直接获取和操作元素。";
        cell.link = "software/codemirror5/mode/facecat/cs.html";
        cell.link2 = "https://gitee.com/facecat007/frame/tree/master/facecat_avalonia";
        cell.linkText1 = "示例";
        cell.linkText2 = "开源";
        cell.image = "images/avalonia.png";
        cell.rate = "80,70,80,60,50,80";
        cell.linkType = "3";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫Pascal框架";
        cell.text2 = "Old";
        cell.text3 = "客户端框架";
        cell.text4 = "用于制作Windows客户端，使用Pascal构建，整个界面仅使用单个窗体进行重绘，直接对接Windows消息，只有一个句柄，所有内部组件都是虚拟出来的，鼠标、输入和滚动均为模拟。绘图代码与框架完全隔离，可以轻易更换，已对接GDI+，使用Html和可视化工具来配置界面，搭配Pascal直接获取和操作元素。";
        cell.link = "software/codemirror5/mode/facecat/pascal.html";
        cell.link2 = "https://gitee.com/facecat007/frame/tree/master/facecat_pascal";
        cell.linkText1 = "示例";
        cell.linkText2 = "开源";
        cell.image = "images/pascal.png";
        cell.rate = "80,90,90,60,60,80";
        cell.linkType = "5";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫MFC框架";
        cell.text2 = "Old";
        cell.text3 = "客户端框架";
        cell.text4 = "用于制作Windows客户端，全部使用C/C++构建，整个界面仅使用单个窗体进行重绘，只有一个句柄，所有内部组件都是虚拟出来的，鼠标、输入和滚动加速均为模拟。绘图代码与框架完全隔离，可以轻易更换，已对接GDI，使用Html和可视化工具来配置界面，搭配C++直接获取和操作元素。";
        cell.link = "software/codemirror5/mode/facecat/cpp.html";
        cell.link2 = "https://gitee.com/facecat007/frame/tree/master/facecat_mfc";
        cell.linkText1 = "示例";
        cell.linkText2 = "开源";
        cell.image = "images/mfc.png";
        cell.rate = "80,100,100,60,80,80";
        cell.linkType = "5";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫Duilib框架";
        cell.text2 = "Old";
        cell.text3 = "客户端框架";
        cell.text4 = "用于制作Windows客户端，全部使用C++构建，整个界面仅使用单个窗体进行重绘，所有内部组件都是虚拟出来的，鼠标、输入和滚动加速均为模拟。绘图代码与框架完全隔离，可以轻易更换，已对接Duilib，使用Html和可视化工具来配置界面，搭配C++直接获取和操作元素。";
        cell.link = "software/codemirror5/mode/facecat/cpp.html";
        cell.link2 = "https://gitee.com/facecat007/frame/tree/master/facecat_duilib";
        cell.linkText1 = "示例";
        cell.linkText2 = "开源";
        cell.image = "images/cpp2.png";
        cell.rate = "80,95,95,60,80,80";
        cell.linkType = "5";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫VB.NET框架";
        cell.text2 = "Old";
        cell.text3 = "客户端框架";
        cell.text4 = "用于制作Windows客户端，使用VB.BET构建，整个界面使用单个窗体重绘，内部元素的触摸、输入和加速滚动操作均为模拟，使用Html和可视化工具来配置界面，搭配VB直接获取和操作元素。";
        cell.link = "software/codemirror5/mode/facecat/xml.html";
        cell.link2 = "https://www.jjmfc.com/software/facecat_vb.zip";
        cell.linkText1 = "示例";
        cell.linkText2 = "下载";
        cell.image = "images/vb.png";
        cell.rate = "90,90,80,60,80,80";
        cell.linkType = "5";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫Lua框架";
        cell.text2 = "Old";
        cell.text3 = "基础框架(内测)";
        cell.text4 = "通过lua51与界面进行通讯，相互调用。";
        cell.link = "software/codemirror5/mode/facecat/xml.html";
        cell.link2 = "document/frame/pic4.jpg";
        cell.linkText1 = "示例";
        cell.linkText2 = "图片";
        cell.image = "images/lua.png";
        cell.linkType = "5";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫QGraphicsView框架";
        cell.text2 = "Fast";
        cell.text3 = "客户端框架";
        cell.text4 = "用于制作客户端，使用Python和QGraphicsView构建，整个界面仅使用单个QGraphicsItem进行重绘，所有内部组件都是虚拟出来的，鼠标、输入和滚动加速均为模拟。绘图代码与框架完全隔离，可以轻易更换，已对接QPainter，使用Html和可视化工具来配置界面，搭配Python直接获取和操作元素。";
        cell.link = "document/frame/pygv.jpg";
        cell.link2 = "https://gitee.com/facecat007/frame/tree/master/facecat_qt/pygv";
        cell.linkText1 = "图片";
        cell.linkText2 = "开源";
        cell.image = "images/qt.png";
        cell.rate = "95,80,80,90,95,80";
        cell.linkType = "4";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫JavaFx框架";
        cell.text2 = "Fast";
        cell.text3 = "客户端+服务端框架";
        cell.text4 = "用于制作要求较高的Windows/Linux客户端和服务，全部使用Java构建，整个界面仅使用单个Canvas进行重绘，所有内部组件都是虚拟出来的，鼠标、输入和滚动加速均为模拟。绘图代码与框架完全隔离，可以轻易更换，已对接GraphicsContext绘图，使用Html和可视化工具来配置界面，搭配Java直接获取和操作元素。通讯服务方面使用原始接口封装，包含长短连接，支持NIO。";
        cell.link = "software/codemirror5/mode/facecat/java.html";
        cell.link2 = "https://www.jjmfc.com/software/facecat_javafx.zip";
        cell.linkText1 = "示例";
        cell.linkText2 = "下载";
        cell.image = "images/java.png";
        cell.rate = "90,70,90,80,95,90";
        cell.linkType = "4";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫Win32 Skia C++框架";
        cell.text2 = "Fast";
        cell.text3 = "客户端框架";
        cell.text4 = "用于制作Windows客户端，全部使用C++构建，整个界面仅使用单个句柄进行重绘，只有一个句柄，所有内部组件都是虚拟出来的，鼠标、输入和滚动加速均为模拟。绘图代码与框架完全隔离，可以轻易更换，已对接Skia，使用Html和可视化工具来配置界面，搭配C++直接获取和操作元素。";
        cell.link = "software/codemirror5/mode/facecat/cpp.html";
        cell.link2 = "https://gitee.com/facecat007/frame/tree/master/facecat_skiacpp";
        cell.linkText1 = "示例";
        cell.linkText2 = "开源";
        cell.image = "images/cpp2.png";
        cell.rate = "95,80,90,60,80,80";
        cell.linkType = "4";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫Ubuntu Skia C++框架";
        cell.text2 = "Fast";
        cell.text3 = "客户端框架(内测)";
        cell.text4 = "用于制作Ubuntu客户端，全部使用C++构建，整个界面仅使用单个窗体进行重绘，所有内部组件都是虚拟出来的，鼠标、输入和滚动加速均为模拟。绘图代码与框架完全隔离，可以轻易更换，已对接SDL2和Skia，使用Html和可视化工具来配置界面，搭配C++直接获取和操作元素。";
        cell.link = "software/codemirror5/mode/facecat/cpp.html";
        cell.link2 = "https://gitee.com/facecat007/frame/tree/master/facecat_skiaucpp";
        cell.linkText1 = "示例";
        cell.linkText2 = "开源";
        cell.image = "images/ubuntu.png";
        cell.rate = "95,80,90,60,80,80";
        cell.linkType = "4";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫Win32 Skia C#框架";
        cell.text2 = "Fast";
        cell.text3 = "客户端框架";
        cell.text4 = "用于制作Windows客户端，全部使用C#构建，整个界面仅使用单个Control进行重绘，只有一个句柄，所有内部组件都是虚拟出来的，鼠标、触摸和滚动加速均为模拟。绘图代码与框架完全隔离，可以轻易更换，已对接Skia，使用Html和可视化工具来配置界面，搭配C#直接获取和操作元素。";
        cell.link = "software/codemirror5/mode/facecat/cs.html";
        cell.link2 = "https://gitee.com/facecat007/frame/tree/master/facacat_skiasharp";
        cell.linkText1 = "示例";
        cell.linkText2 = "开源";
        cell.image = "images/cs2.png";
        cell.rate = "95,80,80,80,80,80";
        cell.linkType = "4";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫Python Skia框架";
        cell.text2 = "Fast";
        cell.text3 = "客户端框架";
        cell.text4 = "用于制作Windows客户端，使用Python构建，整个界面仅使用单个窗体进行重绘，所有内部组件都是虚拟出来的，鼠标、输入和滚动加速均为模拟。绘图代码与框架完全隔离，可以轻易更换，已对接Skia，使用Html和可视化工具来配置界面，搭配Python直接获取和操作元素。";
        cell.link = "software/codemirror5/mode/facecat/python.html";
        cell.link2 = "https://gitee.com/facecat007/template2/tree/master/python/ctp_fast";
        cell.linkText1 = "示例";
        cell.linkText2 = "开源";
        cell.image = "images/python.png";
        cell.rate = "90,80,80,90,80,80";
        cell.linkType = "4";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "花卷猫Go Skia框架";
        cell.text2 = "Fast";
        cell.text3 = "客户端框架";
        cell.text4 = "用于制作Windows客户端，使用Go构建，整个界面仅使用单个窗体进行重绘，所有内部组件都是虚拟出来的，鼠标、输入和滚动均为模拟。绘图代码与框架完全隔离，可以轻易更换，已对接Skia，使用Html和可视化工具来配置界面，搭配Go直接获取和操作元素。";
        cell.link = "software/codemirror5/mode/facecat/go.html";
        cell.link2 = "https://gitee.com/facecat007/template2/tree/master/go/ctp_fast";
        cell.linkText1 = "示例";
        cell.linkText2 = "开源";
        cell.image = "images/go.png";
        cell.rate = "90,80,80,80,80,80";
        cell.linkType = "4";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "JavaScript在线示例";
        cell.text2 = "Demo";
        cell.text3 = "组件示例";
        cell.text4 = "JavaScript+Canvas网页展示框架效果，包含十几个组件的示例。";
        cell.link = "test/example.html";
        cell.link2 = "";
        cell.linkText1 = "打开";
        cell.linkText2 = "";
        cell.linkType = "6";
        cell.rate = "90,80,80,80,70,80";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "Rust在线示例";
        cell.text2 = "Demo";
        cell.text3 = "组件示例";
        cell.text4 = "Wasm网页展示框架效果，包含几个重要组件的示例。";
        cell.link = "http://1.116.142.147:8080";
        cell.link2 = "";
        cell.linkText1 = "打开";
        cell.linkText2 = "";
        cell.linkType = "6";
        cell.rate = "90,80,80,80,70,80";
    }
if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "Go-Wasm在线示例";
        cell.text2 = "Demo";
        cell.text3 = "组件示例";
        cell.text4 = "Wasm网页展示框架效果，包含几个重要组件的示例。";
        cell.link = "http://1.116.142.147:8087";
        cell.link2 = "";
        cell.linkText1 = "打开";
        cell.linkText2 = "";
        cell.linkType = "6";
        cell.rate = "90,80,80,80,70,80";
    }
    
    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "精选案例";
        cell.text2 = "Demo";
        cell.text3 = "应用和代码";
        cell.text4 = "整体产品和业务以国产基础框架和软件为主，以替代国外信息化基建为目标，全部合法合规，无破解、无爬虫、无灰色、无敏感，没有资质牌照的坚决不做，不随便接项目，没有在线保存任何用户信息，互联网和金融方面的内容谨慎发展，未发布生成式AI、区块链、社交IM、互联网经营服务、toC的行情和交易软件，完全没有海外业务和服务。";
        cell.link = "test/industry.html";
        cell.link2 = "";
        cell.linkText1 = "打开";
        cell.linkText2 = "";
        cell.linkType = "6";
        cell.rate = "90,80,80,80,70,80";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "研发历史";
        cell.text2 = "H";
        cell.text3 = "图片和视频";
        cell.text4 = "该框架长期属于作者个人的最优良试验田，自由发挥，从未受利益驱使改变开发方向。基础框架、生态工具和后台服务代码原创度均高于99%，规模庞大，独有代码300万行，从架构，命名到细节均不与任何第三方重复。多数版本仅需操作系统和语言基础SDK支持，无须更多第三方依赖，在国产原创度方面接受一切公开质疑和检验。";
        cell.link = "https://mp.weixin.qq.com/s/y_x4ZJPQo-SPx0imjW4JZQ";
        cell.link2 = "";
        cell.linkText1 = "介绍";
        cell.linkText2 = "";
        cell.linkType = "1";
        cell.rate = "90,80,60,80,60,60";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "联系方式";
        cell.text2 = "C";
        cell.text3 = "微信号等";
        cell.text4 = "花卷猫的各种介绍材料均以官方出具的为准，对于他人不正确或不恰当的宣传，将会进行严厉制止和相关追责。严格保密用户代码和资料，与自研部分做充分隔离，不会在任何地方公布合作单位。";
        cell.link = "test/contact.html";
        cell.link2 = "";
        cell.linkText1 = "打开";
        cell.linkText2 = "";
        cell.linkType = "1";
        cell.rate = "90,80,60,80,60,60";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "实物股东";
        cell.text2 = "F";
        cell.text3 = "资金和设备";
        cell.text4 = "在困难和关键时刻对花卷猫的援助，都将被永远镌刻在官网中，按时间先后顺序排列，后续会优先获得有价值且无风险的超值回报。";
        cell.link = "test/thanks.html";
        cell.link2 = "";
        cell.linkText1 = "打开";
        cell.linkText2 = "";
        cell.linkType = "1";
        cell.rate = "90,80,60,80,60,60";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "头脑股东";
        cell.text2 = "B";
        cell.text3 = "创意和想法";
        cell.text4 = "在任何时候对花卷猫的重要有效建议和点拨，都将被永远镌刻在官网中，按时间先后顺序排列，后续将获得适当的回报得适当的回报。";
        cell.link = "test/ideas.html";
        cell.link2 = "";
        cell.linkText1 = "打开";
        cell.linkText2 = "";
        cell.linkType = "1";
        cell.rate = "90,80,60,80,60,60";
    }

    if (true) {
        let cell = createCell();
        cell.font = "Default,16";
        cell.text1 = "沪ICP备2021003600号 热线电话：15921975627";
        cell.text2 = "";
        cell.text3 = "关于";
        cell.text4 = "";
        cell.link = "https://beian.miit.gov.cn/";
        cell.link2 = "";
        cell.linkText1 = "";
        cell.linkText2 = "";
        cell.linkType = "1";
    }


    updateViewDefault(gPaint.views);
    //刷新界面
    invalidate(gPaint);
    setInterval(checkGridDragScroll, 20);
    </script>
</body>
</html>
